Breaking N

ewsExpert Opini

onInside Sco

opPlain English Who's Talk

ingCompany Profiles
Javology
Cont

ents
|
Feature: Java Serialization
Learn in plain english how to use it.

"Using Serialization, you can seamlessly back up data objects to a file, or send them to distributed Java servers via Remote Method Invocation."

Back to Table of Contents


Understanding Java Serialization

by Govind Seshadri

Data persistency - A basic need

Any halfway-useful application needs data persistency. If you've been wondering if there is a simple way to keep objects persistent in Java, you've certainly chosen the right time to have started to think about the issue. The JDK 1.1 provides us with the Object Serialization mechanism to tackle the once notorious problem of object persistency. Using Serialization, you can seamlessly back up data objects to a file, or send them to distributed Java servers via Remote Method Invocation.

As its name probably implies, Serialization converts Java objects into a byte stream, which can then be easily stored to a file. When the file is later read, the byte stream can be easily converted to the original objects.

But what about JDBC?

Some of you may be asking, "Don't I already have JDBC to keep my data persistent?" While it's true that storing data within a full-fledged database would obviously take care of the persistency issue, it would be like using a sledgehammer to pound a nail. JDBC is a fairly complex interface that allows you to integrate high-powered relational databases into your Java applications. If your application is a fairly small departmental application, with a storage requirement on the order of a few hundred records, using an Oracle or Sybase database as the repository is pure overkill. The problem can be solved more easily with a flat-file storage mechanism utilizing Serialization.

Even Relational databases may not be your answer if your storage needs are extremely large, and if you have a large end-user community requiring a high-throughput system. Keep in mind that every time you need to store/retrieve data from a Relational database, you need to map data stored within two-dimensional tables to Java objects. This mapping would not only sap programmer productivity, but also affect overall system performance. An ideal solution for large, mission-critical applications would be to use Object databases. Even though there is a fairly steep learning-curve in ramping up to this new paradigm, it may be well worth exploring in the future.

Under the hood

Let's try and understand the workings of object Serialization through the following example:
Listing 1 Person.java

public class Person implements java.io.Serializable {

	int id;
	String name;
	String addr;

	public Person(int key, String n, String a) {
			id = key;
			name=n;
			addr=a;
	}
}
 
There is nothing unusual about the Person class in Listing 1, except that it implements the Serializable interface. All objects that are converted to a byte stream during Serialization need to implement the Serializable interface.
Listing 2 Rolodex.java 

class Rolodex implements java.io.Serializable {

 Person[] data =new Person[5];
      
 public Rolodex() {
	data[0] = new Person(100,"Lazy Larry","123 Easy Drive");
	data[1] = new Person(101,"Happy Harry","30 Sunset Ave");
	data[2] = new Person(102,"Big Bessie","11 Market Way");
	data[3] = new Person(103,"Guitar Man","461 Ocean Blvd");
	data[4] = new Person(104,"Java Joe","1 Hacker Ave");
 }

 public void display() {
	for (int i=0; i<5;i++) {
		System.out.println("ID: "+data[i].id);
		System.out.println("NAME: "+data[i].name);
		System.out.println("ADDR: "+data[i].addr);
	}
 }
}
Listing 2 shows the Rolodex class, which also implements the Serializable interface. This class is essentially an array of Person objects, initialized with some values. We will see how we can seamlessly read and write an object of this class to a file using Serialization.
Listing 3 RoloWrite.java	

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

public class RoloWrite {
              
 public static void main(String[] args) {             
	  Rolodex rolodex = new Rolodex();

	  try {
		  FileOutputStream fo = 
			new FileOutputStream("rolodata");
		  ObjectOutputStream serial = 
			new ObjectOutputStream(fo);

		  serial.writeObject(rolodex);
		  serial.flush();
	  }
	  catch (Exception e) {
		  System.out.println("Error during object 
		    serialization");
	  }
 }
}
Listing 3 shows the RoloWrite class, which demonstrates how easily a Java object can written to a file, after first converting it to a byte stream. We first create an object of the Rolodex class, which we intend to keep persistent. The FileOutputStream object is created because we need some stream object to attach our ObjectOutputStream to. The ObjectOutputStream object created by attaching the stream now contains all the necessary functionality to serialize any Java object and write it to the stream.

To write our Rolodex object out to the stream, all we have to do is invoke the writeObject method of the ObjectOutputStream as in serial.writeObject(rolodex);

Notice that we did not have to make any other conversion to the object itself in trying to make it persistent. We simply just wrote the object to the stream, as is!

Listing 4 RoloRead.java 

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class RoloRead {
                 
 public static void main(String[] args) {                
	Rolodex rolodex=null;

	try {
		FileInputStream fi = 
			new FileInputStream("rolodata");
		ObjectInputStream serial = 
			new ObjectInputStream(fi);
		rolodex =(Rolodex) serial.readObject();
	}
	catch (Exception e) {
		System.out.println("Error during object 
			serialization");
	}

	rolodex.display();
 }
}
The RoloRead class shown in Listing 4, first opens a stream to the data file using FileInputStream. Once we attach this stream to the ObjectInputStream object, we are ready to read the object, via the readObject method. Notice that the object returned by readObject needs to be cast to your target class - Rolodex, as Java does not automatically do this for you. On calling the display method on the Rolodex retrieved object, it's contents are displayed.

RoloWrite.java and RoloRead.java can be compiled as usual. When you run RoloRead after creating an image of the object by first running RoloWrite, you get the following output:

	ID: 100
	NAME: Lazy Larry
	ADDR: 123 Easy Drive
	ID: 101 
	NAME: Happy Harry
	ADDR: 30 Sunset Ave
	ID: 102
	NAME: Big Bessie 
	ADDR: 11 Markey Way
	ID: 103 
	NAME: Guitar Man
	ADDR: 461 Ocean Blvd
	ID: 104
	NAME: Java Joe
	ADDR: 1 Hacker Ave

One size doesn't fit all

Although Serialization provides a neat and simple interface for object persistency, it is best suited for applications that use only a small amount of data, where concurrent access to data is not required. Since Serialization reads/writes entire objects after converting them into a byte stream, system throughput suffers if your objects are greater than, say, a megabyte. System performance also lags if your application is either read- or write- intensive, for the same reason. It should be noted that Serialization does not provide any of the more advanced database features like file locking, record locking, commits, rollbacks, etc. Hence, they may not be suited for applications where reliability is paramount.


Author footnote...

Govind Seshadri leads Java development at MGIC Investment Corporation. His primary areas of interest include design of large-scale Java Client/Server systems, Network Security and Electronic Commerce. Govind holds Bachelors and Masters degrees in Computer Science. He can be reached at Govind_Seshadri@mgic.com

| Breaking News | Expert Opinion | Inside Scoop | Plain English | Who's Talking? | Company Profiles |
© 1997 Javology