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();
The total number of items is calculated using the
order.icost
field.
if(order.apples.length() > 0){
try{
applesNo = Integer.valueOf(order.apples);
order.itotal += applesNo.intValue();
} catch (java.lang.NumberFormatException e) {
appleqnt.setText("Invalid Value");
}
} else {
order.itotal += 0;
}
The total number of items is retrieved from the
order.itotal
field and displayed in the
user interface.
num = new Integer(order.itotal);
text = num.toString();
this.items.setText(text);
Similarly, the total cost is calculated and displayed in the
user interface using the order.icost
field.
order.icost = (order.itotal * 1.25);
cost = new Double(order.icost);
text2 = cost.toString();
this.cost.setText(text2);
try{
send.sendOrder(order);
} catch (Exception e) {
System.out.println("Cannot send data to server");
}
After the totals are calculated, the order
object is sent over the net to the server program.
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
.
Send.java
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;
}
RemoteServer.java
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.
RemoteServer.java
public void sendOrder(DataOrder order){
value += 1;
num = new Integer(value);
orders = num.toString();
try{
FileOutputStream fos =
new FileOutputStream(orders);
ObjectOutputStream oos =
new ObjectOutputStream(fos);
oos.writeObject(order);
}catch (java.io.FileNotFoundException e){
System.out.println(e.toString());
}catch (java.io.IOException e){
System.out.println(e.toString());
}
}
The RemoteServer.getOrder
method
does what the sendOrder
method does in
reverse using the get
variable to keep
track of which orders have been viewed.
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();
try{
FileInputStream fis =
new FileInputStream(orders);
ObjectInputStream ois =
new ObjectInputStream(fis);
order = (DataOrder)ois.readObject();
}catch (java.io.FileNotFoundException e){
System.out.println(e.toString());
}catch (java.io.IOException e){
System.out.println(e.toString());
}catch (java.lang.ClassNotFoundException e){
System.out.println(e.toString());
}
}else{
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){
try{
order = send.getOrder();
creditNo.setText(order.cardnum);
customerNo.setText(order.custID);
applesNo.setText(order.apples);
peachesNo.setText(order.peaches);
pearsNo.setText(order.pears);
cost = order.icost;
price = new Double(cost);
unit = price.toString();
icost.setText(unit);
items = order.itotal;
itms = new Integer(items);
i = itms.toString();
itotal.setText(i);
} 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 JavaTM Tutorial.
[TOP]