Lesson 4: Serialization

One big problem with the example program in its current form is the fact that sending clients can overwrite each other's data before receiving clients have a chance to get and process it. This lesson adapts the server code to ensure all orders are processed (nothing is overwritten), and all orders are processed in the order they are received by the server.

About the Example

The example adapts the Part 2, Lesson 2: User Interfaces Revisited example to wrap the fruit order data into a single data object and send the data object over the network to the server. This is more efficient than sending each unit of data separately.

Wrapping the Data

The DataOrder.java class is very simple. It defines the fields that wrap and store the fruit order data. It has no methods. It implements the Serializable interface so its data can be serialized, and written to and read from a file as a single unit.

Object serialization transforms an object's data to a bytestream that represents the state of the data. The serialized form of the data contains enough information to recreate the object with its data in a similar state to what it was when saved.

import java.io.*;

class DataOrder implements Serializable{
  String apples, peaches, pears, cardnum, custID;
  double icost;
  int itotal;

Sending Data

The RMIClient1.java program is modified to use the DataOrder class to send the order data over the net. The RMIClient1.actionPerformed method creates an instance of the DataOrder class and initializes its fields with order data retrieved from the user interface text fields and areas.

  public void actionPerformed(ActionEvent event){

   Object source = event.getSource();
   Integer applesNo, peachesNo, pearsNo, num;
   Double cost;
   String number, text, text2;
   DataOrder order = new DataOrder();

   if(source == purchase){
    order.cardnum = creditCard.getText();
    order.custID = customer.getText();
    order.apples = appleqnt.getText();
    order.peaches = peachqnt.getText();
    order.pears = pearqnt.getText();


   if(order.apples.length() > 0){

       applesNo = Integer.valueOf(order.apples);
       order.itotal += applesNo.intValue();
     } catch (java.lang.NumberFormatException e) {
       appleqnt.setText("Invalid Value");
   } else {
        order.itotal += 0;


 num = new Integer(order.itotal);

  text = num.toString();


 order.icost = (order.itotal * 1.25);

 cost = new Double(order.icost);
 text2 = cost.toString();

 } catch (Exception e) {
    System.out.println("Cannot send data to server");


Server Program

The Send.java and RemoteServer.java classes are much simpler in this lesson. They have one getXXX method that returns an instance of DataOrder, and one setXXX method that accepts an instance of DataOrder.


import java.rmi.Remote;

import java.rmi.RemoteException;

public interface Send extends Remote {
  public void sendOrder(DataOrder order) 
    throws RemoteException;
  public DataOrder getOrder() throws RemoteException;


The RemoteServer.sendOrder method accepts a DataOrder instance as input, and stores each order in a separate file where the file name is a number. The first order received is stored in a file named 1, the second order is stored in a file named 2, and so forth.

To keep track of the file names, the value variable is incremented by 1 each time the sendOrder method is called, converted to a String, and used for the file name in the serialization process.

Objects are serialized by creating a serialized output stream and writing the object to the output stream. In the code, the first line in the try block creates a FileOutputStream with the file name to which the serialized object is to be written.

The next line creates an ObjectOutputFileStream from the file output stream. This is the serialized output stream to which the order object is written in the last line of the try block.


public void sendOrder(DataOrder order){

  value += 1;
  num = new Integer(value);
  orders = num.toString();
    FileOutputStream fos = 
      new FileOutputStream(orders);
    ObjectOutputStream oos = 
      new ObjectOutputStream(fos);
  }catch (java.io.FileNotFoundException e){
  }catch (java.io.IOException e){


But first, this method checks the value variable. If it is equal to zero, there are no orders to get from a file and view, and if it is greater than the value in the get variable, there is at least one order to get from a file and view. As each order is viewed, the get variable is incremented by 1.

  public DataOrder getOrder(){

    DataOrder order = null;

    if(value == 0){
      System.out.println("No Orders To Process");

    if(value > get){
      get += 1;
      num = new Integer(get);
      orders = num.toString();
        FileInputStream fis = 
          new FileInputStream(orders);
        ObjectInputStream ois = 
          new ObjectInputStream(fis);
        order = (DataOrder)ois.readObject();
      }catch (java.io.FileNotFoundException e){
      }catch (java.io.IOException e){
      }catch (java.lang.ClassNotFoundException e){
      System.out.println("No Orders To Process");
   return order;

Receiving Data

The RMIClient2.actionPerformed method gets an order object and references its fields to display data in the user interface.

if(source == view){

    order  = send.getOrder();

    cost = order.icost;
    price = new Double(cost);
    unit = price.toString();

    items = order.itotal;
    itms = new Integer(items);
    i = itms.toString();
  } catch (Exception e) {
    System.out.println("Cannot send data to server");

More Information

You can find more information on serialization in the Reading and Writing (but no 'rithmetic) lesson in The Java Tutorial.