Easy to Learn Java: Programming Articles, Examples and Tips

Start with Java in a few days with Java Lessons or Lectures

Home

Code Examples

Java Tools

More Java Tools!

Java Forum

All Java Tips

Books

Submit News
Search the site here...
Search...
 
Search the JavaFAQ.nu
1000 Java Tips ebook

1000 Java Tips - Click here for the high resolution copy!1000 Java Tips - Click here for the high resolution copy!

Java Screensaver, take it here

Free "1000 Java Tips" eBook is here! It is huge collection of big and small Java programming articles and tips. Please take your copy here.

Take your copy of free "Java Technology Screensaver"!.

Easy Learn Java: Programming Articles, Examples and Tips - Page 334


Previous 1060 Stories (530 Pages, 2 Per Page) Next

Serializing Objects Into Database

Go to all tips in Story by Dr. Kabutz
2001-05-24 The Java Specialists' Newsletter [Issue 020] - Serializing Objects Into Database

2001-05-24 The Java Specialists' Newsletter [Issue 020]

Serializing Objects Into Database

Author: Dr. Heinz M. Kabutz

JDK version:

Category: Language

You can subscribe from our home page: http://www.javaspecialists.co.za (which also hosts all previous issues, available free of charge Smile

Welcome to the 20th issue of "The Java(tm) Specialists' Newsletter", where I look at how we can serialize objects into a database using JDBC. Thank you for your continued support, it makes the hours of research and writing worthwhile Smile

This week's newsletter has been the most frustrating one to write; databases usually have that effect on me. Forgive me if this newsletter seems too elementary, I've actually in the past had to dig into the C code of the JDBC-ODBC bridge to figure out why it wasn't working, i.e. it's more complicated than it seems. Java truly is a "write-once-debug-everywhere" language, especially when it comes to JDBC drivers.

If you're crazy enough to use MSSQL as your database, which isn't THAT crazy considering the beautiful administrative tools available and the ease with which it can be set up, you might consider using the JDBC-ODBC bridge to access the database. It's a dog, full of bugs, but it's free (if you don't count the developer's time in writing workarounds as significant). Also, "better the devil you know", which according to "The Wordsworth Dictionary of Cliche" means "Trust the person or thing you are familiar with rather than risking the unknown." Other JDBC drivers are bound to also contain bugs, and at least we know the bugs in the bridge!

Serializing Objects Into Database

A problem I faced a few months ago, before JDK 1.3 was released with an improved JDBC-ODBC bridge, was how to serialize objects into a relational database using JDBC. At the time, it was quite tricky to do because of bugs in the ODBC bridge. As soon as the object became bigger than 2000 bytes, the method shown below ceased to work. I don't need to mention that I tested it with less than 2000 bytes the first time I wrote the code?

Before we look at how we can write binary objects into a database table, what type of data type should we use? Should we use VARBINARY or IMAGE? The answer, I suppose, depends on how big the object is that you want to write to the database, and which database you're actually talking to (hence my comments regarding write-once-debug-everywhere).

We also have to consider the underlying database when we get a SQLException, so that we can determine what actually went wrong. If the connection goes down temporarily due to a flaky network, it is no good for our application server to crash permanently. In a future newsletter, I will demonstrate how you can find out what went wrong by looking at the SQLException.

Back to the problem of writing serialized Java objects into the database. The most intuitive way of doing it, which as I mentioned before only works in the ODBC bridge of JDK 1.3, is to take the Object, stream it to a ByteArrayOutputStream via an ObjectOutputStream, convert the ByteArrayOutputStream to a byte array and then call the setBytes method on the prepared statement. Note that you have to use PreparedStatement, rather than the normal Statement class, if you want to serialize objects into the database.

To convert it back to a Java object, we simply do the reverse process of reading the byte array, putting it into a ByteArrayInputStream and passing that to an ObjectInputStream. We then read the object, and voila, we have read the object back again.

DatabaseTest.java code below:


//: DatabaseTest.java
import java.sql.*;
import java.io.*;
import java.util.Vector;
public class DatabaseTest {
  public static void write(
      Object obj, PreparedStatement ps, int parameterIndex)
      throws SQLException, IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oout = new ObjectOutputStream(baos);
    oout.writeObject(obj);
    oout.close();
    // This will NOT work in JDBC-ODBC bridge under JDK 1.2.2
    // as soon as the size of the byte array is bigger than 2000

    ps.setBytes(parameterIndex, baos.toByteArray());
  }
  public static Object read(ResultSet rs, String column)
      throws SQLException, IOException, ClassNotFoundException {
    // This will NOT work in JDBC-ODBC bridge under JDK 1.2.2
    // as a SQL NULL data value is not handled correctly.
    byte[] buf = rs.getBytes(column);
    if (buf != null) {
      ObjectInputStream objectIn = new ObjectInputStream(
        new ByteArrayInputStream(buf));
      return objectIn.readObject();
    }
    return null;
  }
  public static void main(String[] args) throws Exception {
    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
    Connection con = DriverManager.getConnection(
      "jdbc:odbc:MailingList", "sa", "");

    Statement st = con.createStatement();
    st.executeUpdate("INSERT BlobTable (Data) VALUES (NULL)");
    st.close();

    PreparedStatement ps = con.prepareStatement(
      "INSERT INTO BlobTable (Data) VALUES (?)");
    write(new Vector(2) {{ add("Hello"); add("World");}}, ps, 1);
    ps.execute();
    Vector veryBig = new Vector(10);
    for (int i=0; i<10; i++) veryBig.add(new byte[10000]);
    write(veryBig, ps, 1);
    ps.execute();
    write("What Gives?", ps, 1);
    ps.execute();
    write(null, ps, 1);
    ps.execute();
    ps.close();

    st = con.createStatement();
    ResultSet rs = st.executeQuery("SELECT Data FROM BlobTable");
    while(rs.next()) {
      System.out.println(read(rs, "Data"));
    }
    rs.close();
    st.close();
  }
}

To test this code, you'll have to set up a DSN to point to your MSSQL database (or a real database), and set up a table in your database called BlobTable with an IMAGE type for the column called "Data". In my example, I am writing a SQL NULL value into the table, then a small Vector (using dynamic aggregate initialization described in Newsletter 002) and after that a very big Vector, followed by a String and a Java null object. Lastly, I close the PreparedStatement, and read all the objects back and print them to the screen.

The output on my system is:

null
[Hello, World]
[[B@2f0db, [B@12d342, [B@6b97fd, [B@478e57, [B@5224ee, [B@76a746, 
[B@5ff48b, [B@2ffc70, [B@663e3d, [B@4901] What Gives?
null

All very simple, except that in a real environment we don't really want to use IMAGE types in our database, unless absolutely necessary. We would prefer using VARBINARY as they take less space and form part of the block of data in the row. How do we know the size of a Java object in memory? I've worked out some formulae for "guessing" the size of a Java object by looking at its data members, which is a topic for another newsletter. In the meantime, the easiest is to take the biggest set of data that must be supported by your object and simply try out how much space it will take. There is no "sizeof()" method in Java to do that for you, unfortunately.

Some other issues related to the above problem is that a PreparedStatement is bound to a Connection, which means that we cannot rebind it to another Connection. The result is that we cannot use Connection pooling very well for this, as we then have to construct a new PreparedStatement each time we want to insert a Java object into the database, which defeats the reason for having a PreparedStatement. In the JDBC 3.0 specification, there is support for rebinding PreparedStatements, but we'll have to wait a bit before we'll have JDBC 3.0 compliant drivers.

How do you do this with JDK 1.2.x? You have to use the PreparedStatement.setBinaryStream(...) method to write the binary stream directly into the database. The problem is that when you read the binary stream again, and the database contained a SQL NULL, you get some nasty exceptions that are hard to figure out. Obviously, the JDK 1.3.x ODBC bridge throws different exceptions, so I don't advocate using the JDK 1.2.x bridge for writing objects into databases.

---
Warning Advanced:
A memory leak, discovered by the best and most ruthless Java bug finder I know, occurs when you call the ResultSet.getTimestamp() method. Rather call ResultSet.getString() and convert the resultant String to a Date object. He's recently been granted permanent residence in our beautiful country of South Africa, which is quite a feat, considering the tough immigration laws. Congratulations!
---

Please send me your comments / experiences on this. I always appreciate any feedback, both positive and negative, and please remember to send this newsletter to others who might be interested in Java.

Heinz


Copyright 2000-2004 Maximum Solutions, South Africa

Reprint Rights. Copyright subsists in all the material included in this email, but you may freely share the entire email with anyone you feel may be interested, and you may reprint excerpts both online and offline provided that you acknowledge the source as follows: This material from The Java(tm) Specialists' Newsletter by Maximum Solutions (South Africa). Please contact Maximum Solutions for more information.

Java and Sun are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. Maximum Solutions is independent of Sun Microsystems, Inc.

7937 bytes more | 4 comments | Printer Friendly Page  Send to a Friend | Score: 0
Posted by jalex on Sunday, April 03, 2005 (00:00:00) (4361 reads)

Java Lesson 41: Exception handling with try, catch, and finally blocks

Go to all tips in Java Lessons by Jon Huhtala
All Java Lessons contents page | Java Lesson 1 | Java Lesson 2 | Java Lesson 3 | Java Lesson 4 | Java Lesson 5 | Java Lesson 6 | Java Lesson 7 | Java Lesson 8 | Java Lesson 9 | Java Lesson 10 | Java Lesson 11 | Java Lesson 12 | Java Lesson 13 | Java Lesson 14 | Java Lesson 15 | Java Lesson 16 | Java Lesson 17 | Java Lesson 18 | Java Lesson 19 | Java Lesson 20 | Java Lesson 21 | Java Lesson 22 | Java Lesson 23 | Java Lesson 24 | Java Lesson 25 | Java Lesson 26 | Java Lesson 27 | Java Lesson 28 | Java Lesson 29 | Java Lesson 30 | Java Lesson 31 | Java Lesson 32 | Java Lesson 33 | Java Lesson 34 | Java Lesson 35 | Java Lesson 36 | Java Lesson 37 | Java Lesson 38 | Java Lesson 39 | Java Lesson 40 | Java Lesson 41 | Java Lesson 42 | Java Lesson 43 | Java Lesson 44 | Java Lesson 45 | Java Lesson 46

Java Lesson 41 by Jon Huhtala

Exception handling with try, catch, and finally blocks


Overview

One of the major differences between commercial quality programs and those we have written and studied so far is in their ability to survive various error conditions. For example, it is relatively difficult to make programs like Microsoft Word or Adobe Acrobat Reader crash. If they did crash easily, they would not be on the market for long.

Operating systems in particular must survive nearly any error that can occur. If the operating system fails, the entire system is brought down and all currently executing programs come to an abrupt end. The result can be devastating with work being lost and files being corrupted. The ability of competing operating systems (such as Windows and Unix) to detect and recover from errors is a constant source of debate among their advocates.

In an effort to make software fail-safe, estimates are that as much as 90% of the code in a commercial product is there to detect and recover from errors that might never occur. But, it is best to be prepared.

As a robust language, Java provides built-in language features, interfaces, and classes that help a programmer detect and recover from a wide range of conditions that would otherwise result in program failure.

Some conditions are more severe than others but all are Throwable objects in Java. The Throwable class is the root class for all errors and exceptions and is part of the java.lang package. When an error or exception occurs, an object is constructed that encapsulates the condition and it is "thrown". If and how the object is "caught" will be covered shortly.

Errors

  • Are encapsulated by the Error class (an extension of Throwable) and its descendent classes (such as VirtualMachineError, ThreadDeath, AWTError, etc.)

  • Are serious conditions that a reasonable application is not expected to detect and from which it is not expected to recover. For example, an OutOfMemoryError (a descendent of VirtualMachineError) will occur if the JVM has run out of memory. There is little an application can do about this condition.

  • Are considered abnormal conditions that should never occur. For that reason, we will not worry about them in our typical application programs.

...........

Exceptions

  • Are encapsulated by the Exception class (an extension of Throwable), its many descendent classes (such as RuntimeException and IOException), and their many descendent classes (such as ArithmeticException, NullPointerException, EOFException, ArrayIndexOutOfBoundsException, SocketException, etc.).

  • Are less serious conditions that a reasonable application can anticipate and from which it may recover

  • May result from poor programming. For example, this poorly written program is a simulation of the old "shell game". The user is asked to pick a number from 1 to 3 to locate an object stored at random within a three element array. Unfortunately, the other array elements are null. If the user picks the correct number, they win. If they don't, a NullPointerException will occur. The user can also generate an ArrayIndexOutOfBoundsException if they pick a number other than 1, 2, or 3.

public class App {
public static void main(String[] args) {

// Loop control variable.

char again = 'y';

// Main loop. One array is entered and processed in each iteration.

while (again == 'Y' || again =='y') {

// Instantiate a three element array and load a single String
// at a random element location.

String[] strings = new String[3];
int randomIndex = (int) ((Math.random()*100) % strings.length);
strings[randomIndex] = "Lucky";

// Ask the user to guess the element location.

Utility.separator(50, '>');
System.out.print("Pick a number from 1 to " + strings.length + ": ");

// If they guess the element location, display a message. Otherwise,
// an exception will occur to terminate processing.

if (strings[Keyboard.readInt() - 1].equals("Lucky")) {
Utility.skip();
System.out.println(" YOU WIN!!!");
}

// Ask the user if they want to do it again and repeat the loop as
// requested.

Utility.separator(40, '=');
System.out.print("Again? (Y/N): ");
again = Keyboard.readChar();
}
}
}

Note: Run this program several times and notice the exceptions that occur. Be sure to enter a number other than 1, 2, or 3 at least once. We will correct these errors shortly.

The exception handling technique

  • Involves the use of the try, catch, and finally Java keywords

  • Consists of several steps

  1. try a block of code that may result in an exception being "thrown"

  2. Code one or more blocks designed to automatically catch and handle a specific type of exception if one occurs. At most, only one of these blocks can be called in a single pass through the code. If none of the specified exceptions occurs, none of the blocks will be executed.

  3. Optionally code a block that will finally be run in ALL situations, whether an exception occurs or not

  • Has the following general syntax:

try {
statements that may result in an exception being thrown;
}
catch (exception-type1 reference) {
statements to handle the exception
;
}
catch (exception-type2 reference) {
statements to handle the exception
;
}
other catch blocks...
finally {
statements to be ALWAYS executed
;
}

where exception-typeN is the class name of the exception to be caught (such as NullPointerException) and reference is its local object reference within the catch block.

Example: The following is a modified version of the "shell game" program presented earlier. It contains a try block and two catch blocks. One handles a NullPointerException and the other handles an ArrayIndexOutOfBoundsException. No finally block is specified, so logic comes together after the end of the last catch block.

public class App {
public static void main(String[] args) {

// Loop control variable.

char again = 'y';

// Main loop. One array is entered and processed in each iteration.

while (again == 'Y' || again =='y') {

// Instantiate a three element array and load a single String
// at a random element location.

String[] strings = new String[3];
int randomIndex = (int) ((Math.random()*100) % strings.length);
strings[randomIndex] = "Lucky";

// Ask the user to guess the element location.

Utility.separator(50, '>');
System.out.print("Pick a number from 1 to " + strings.length + ": ");

// "Try" to read their response, use it to index into the array,
// and see if they win.

try {

// If they guess the element location, display a message. Otherwise,
// an exception will occur.

if (strings[Keyboard.readInt() - 1].equals("Lucky")) {
Utility.skip();
System.out.println(" YOU WIN!!!");
}
}

// This block is automatically executed if a NullPointerException
// occurs to indicate a null array location.

catch (NullPointerException err) {
Utility.skip();
System.out.println(" Empty shell - YOU LOSE!!!");
}

// If an ArrayIndexOutOfBoundsException occurs, this block is
// automatically executed. It indicates an invalid number was
// used as an index.

catch (ArrayIndexOutOfBoundsException err) {
Utility.skip();
System.out.println(" Invalid number - YOU LOSE");
}

// Ask the user if they want to do it again and repeat the loop as
// requested.

Utility.separator(40, '=');
System.out.print("Again? (Y/N): ");
again = Keyboard.readChar();
}
}
}

Note: The catch blocks are mutually exclusive. In a single iteration you may not process within more than one catch block.

Special considerations

  • A catch block for a superclass exception will catch all descendent exceptions. This makes the order of the catch blocks important. For example,

public class App {
public static void main(String[] args) {
try {
int x = 3 / 0;
}
catch (ArithmeticException err) {
System.out.println(err.getMessage());
}
catch (Exception err) {
System.out.println("An error has occurred");
}
}
}

will result in the message "/ by zero" being displayed because the getMessage() method of an Exception objects and its descendents returns a message associated with the exception. while,

public class App {
public static void main(String[] args) {
try {
int x = 3 / 0;
}
catch (Exception err) {
System.out.println("An error has occurred");
}
catch (ArithmeticException err) {
System.out.println(err.getMessage());
}
}
}

results in a compile error that says the second catch block is unreachable.

Because the Exception class is the ancestor of all other exception classes, a general-purpose catch block may be coded as

catch (Exception err) {
System.out.println(err.getMessage());
}

and may be the only catch block. Alternatively, this general-purpose catch block may be placed at the end of all other catch blocks to become the default catch block. It would automatically be called if an exception is thrown that doesn't match the more specific exceptions in the preceding catch blocks.

  • If an exception is thrown for which there is no corresponding catch block (either a specific exception type or an ancestor exception type), the JVM "unwinds the stack". It terminates the currently executing method and looks backward through the call stack looking for a catch block that can handle the exception. If none is found, the JVM itself is terminated and the application ends.

  • No actual processing is required to "catch" an exception. For example, the JVM will permit processing to continue if a catch block like the following is coded.

catch (Exception err) {}

As far as the JVM is concerned, the exception has been handled.

  • The compiler checks to see if your code is prepared to handle certain exceptions. Such "checked exceptions" require you to use try and catch blocks in order to successfully compile. Many checked exceptions will be covered in later lessons when we address Java input and output.

Exceptions that descend from RuntimeException are NOT checked by the compiler. Programs that might fail due to such exceptions do not require try and catch blocks.

  • Calling a method that might throw a checked exception must be called within a try block and must catch the thrown exception (or an ancestor) in order to compile. Throwing an exception will be covered in the next lesson.

  • A try, catch, finally sequence can be nested anywhere within another try, catch, finally sequence.

  • A catch block must have a corresponding try block. It can not stand alone. Similarly a finally block must have a corresponding try block. The compiler detects such errors.

  • The compiler will permit a try block with no catch blocks if a finally block is coded. If an exception occurs, however, the finally block will execute and then the stack will be unwound. For example,

public class App {
public static void main(String[] args) {
try {
int x = 3 / 0;
}
finally {
System.out.println("I'm about to unwind");
}
}
}

compiles fine. When executed, however, an uncaught ArithmeticException occurs. The finally block is executed prior to unwinding the stack.

Lab exercise for Ferris students

E-mail your answers to this assignment no later than the due date listed in the class schedule.

Review questions

  1. Assuming all unseen code is correct, which of the following will be part of the output displayed by executing the following statements? The line numbers are for reference purposes only. (choose four)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
try {
int[] numbers = new int[3];
System.out.println("Message 1");
numbers[3] = 5;
System.out.println("Message 2");
}
catch (ArrayIndexOutOfBoundsException err) {
System.out.println("Message 3");
}
catch (Exception err) {
System.out.println("Message 4");
}
finally {
System.out.println("Message 5");
}
System.out.println("Message 6");
  1. Message 1

  2. Message 2

  3. Message 3

  4. Message 4

  5. Message 5

  6. Message 6

  1. Assuming all unseen code is correct, what will be displayed when the following statements are executed? The line numbers are for reference purposes only.

1
2
3
4
5
6
7
8
9
10
11
try {
StringBuffer[] s = new StringBuffer[10];
s[0].reverse();
}
catch (ArrayIndexOutOfBoundsException err) {
System.out.println("Message 1");
}
catch (Exception err) {
System.out.println("Message 2");
}
System.out.println("Message 3");
  1. the statements will not compile

  2. the program will terminate with nothing being displayed

  3. Message 1
    Message 3

  4. Message 2
    Message 3

  5. Message 3

  1. Assuming all unseen code is correct, what will be displayed when the following statements are executed? The line numbers are for reference purposes only.

1
2
3
4
5
6
7
8
9
10
try {
double x = 17.5 / 0.0;
}
catch (Exception err) {
System.out.println("Message 1");
}
finally {
System.out.println("Message 2");
}
System.out.println("Message 3");
  1. the statements will not compile

  2. the program will terminate with nothing being displayed

  3. Message 1
    Message 2
    Message 3

  4. Message 2
    Message 3

  5. Message 3

  1. Assuming all unseen code is correct, what will be displayed when the following statements are executed? The line numbers are for reference purposes only.

1
2
3
4
5
6
try {
int x = 3 / 0;
}
catch (Exception err) {
}
System.out.println("Message 1");
  1. the statements will not compile

  2. the program will terminate with nothing being displayed

  3. Message 1


25095 bytes more | 8 comments | Printer Friendly Page  Send to a Friend | Score: 0
Posted by jalex on Sunday, April 03, 2005 (00:00:00) (15312 reads)

Previous 1060 Stories (530 Pages, 2 Per Page) Next

530| 529| 528| 527| 526| 525| 524| 523| 522| 521| 520| 519| 518| 517| 516| 515| 514| 513| 512| 511| 510| 509| 508| 507| 506| 505| 504| 503| 502| 501| 500| 499| 498| 497| 496| 495| 494| 493| 492| 491| 490| 489| 488| 487| 486| 485| 484| 483| 482| 481| 480| 479| 478| 477| 476| 475| 474| 473| 472| 471| 470| 469| 468| 467| 466| 465| 464| 463| 462| 461| 460| 459| 458| 457| 456| 455| 454| 453| 452| 451| 450| 449| 448| 447| 446| 445| 444| 443| 442| 441| 440| 439| 438| 437| 436| 435| 434| 433| 432| 431| 430| 429| 428| 427| 426| 425| 424| 423| 422| 421| 420| 419| 418| 417| 416| 415| 414| 413| 412| 411| 410| 409| 408| 407| 406| 405| 404| 403| 402| 401| 400| 399| 398| 397| 396| 395| 394| 393| 392| 391| 390| 389| 388| 387| 386| 385| 384| 383| 382| 381| 380| 379| 378| 377| 376| 375| 374| 373| 372| 371| 370| 369| 368| 367| 366| 365| 364| 363| 362| 361| 360| 359| 358| 357| 356| 355| 354| 353| 352| 351| 350| 349| 348| 347| 346| 345| 344| 343| 342| 341| 340| 339| 338| 337| 336| 335|
334
| 333| 332| 331| 330| 329| 328| 327| 326| 325| 324| 323| 322| 321| 320| 319| 318| 317| 316| 315| 314| 313| 312| 311| 310| 309| 308| 307| 306| 305| 304| 303| 302| 301| 300| 299| 298| 297| 296| 295| 294| 293| 292| 291| 290| 289| 288| 287| 286| 285| 284| 283| 282| 281| 280| 279| 278| 277| 276| 275| 274| 273| 272| 271| 270| 269| 268| 267| 266| 265| 264| 263| 262| 261| 260| 259| 258| 257| 256| 255| 254| 253| 252| 251| 250| 249| 248| 247| 246| 245| 244| 243| 242| 241| 240| 239| 238| 237| 236| 235| 234| 233| 232| 231| 230| 229| 228| 227| 226| 225| 224| 223| 222| 221| 220| 219| 218| 217| 216| 215| 214| 213| 212| 211| 210| 209| 208| 207| 206| 205| 204| 203| 202| 201| 200| 199| 198| 197| 196| 195| 194| 193| 192| 191| 190| 189| 188| 187| 186| 185| 184| 183| 182| 181| 180| 179| 178| 177| 176| 175| 174| 173| 172| 171| 170| 169| 168| 167| 166| 165| 164| 163| 162| 161| 160| 159| 158| 157| 156| 155| 154| 153| 152| 151| 150| 149| 148| 147| 146| 145| 144| 143| 142| 141| 140| 139| 138| 137| 136| 135| 134| 133| 132| 131| 130| 129| 128| 127| 126| 125| 124| 123| 122| 121| 120| 119| 118| 117| 116| 115| 114| 113| 112| 111| 110| 109| 108| 107| 106| 105| 104| 103| 102| 101| 100| 99| 98| 97| 96| 95| 94| 93| 92| 91| 90| 89| 88| 87| 86| 85| 84| 83| 82| 81| 80| 79| 78| 77| 76| 75| 74| 73| 72| 71| 70| 69| 68| 67| 66| 65| 64| 63| 62| 61| 60| 59| 58| 57| 56| 55| 54| 53| 52| 51| 50| 49| 48| 47| 46| 45| 44| 43| 42| 41| 40| 39| 38| 37| 36| 35| 34| 33| 32| 31| 30| 29| 28| 27| 26| 25| 24| 23| 22| 21| 20| 19| 18| 17| 16| 15| 14| 13| 12| 11| 10| 9| 8| 7| 6| 5| 4| 3| 2| 1|


Home Code Examples Java Forum All Java Tips Books Submit News, Code... Search... Offshore Software Tech Doodling

RSS feed Java FAQ RSS feed Java FAQ News     

    RSS feed Java Forums RSS feed Java Forums

All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest 1999-2006 by Java FAQs Daily Tips.

Interactive software released under GNU GPL, Code Credits, Privacy Policy