Communities
|
Social Applications
Networks
Support
|
|
C-Level Executives
Other Roles
|
|
Support
Education
Partner
Other Tasks
|
|
[ <<BACK] [ CONTENTS] [ NEXT>>]
In Java Programming Language Basics, Part 1, you learned how to use Java Foundation Classes (JFC) Project Swing (Project Swing) components to build a simple user interface with very basic backend functionality. You also learned how to use the Remote Method Invocation (RMI) application programming interface (API) to send data from a client program to a server program on the net where the data can be accessed by other client programs.
This lesson takes the RMI application from Part 1, Lesson 8: Remote Method Invocation, creates a more involved user interface, and uses a different layout manager. These changes give you the beginnings of a very simple electronic-commerce application that consists of two types of client programs: one lets end users place purchase orders and the other lets order processors view the orders.
| |
This is a very simple electronic commerce example for instructional purposes only. It consists of three programs: two client programs, one for ordering fruit and another for viewing the order, and one server program that makes order information available to clients that view the orders.
The FruitClient program presents a user interface and prompts the end user to order apples, peaches, and pears at $1.25 each.
After the end user enters the number of each item to order, he or she presses the Return key to commit the order and update the running total.
The Tab key or mouse moves the cursor to the next field. At the bottom, the end user provides a credit card number and customer ID.
When the end user clicks
Purchase, all values entered into the form are sent to the server program.
The end user must press the Return key for the total to update. If the Return key is not pressed, an incorrect total is sent across the net with the order. The end of this lesson asks you to change the code so there is no danger incorrect totals are sent across the net because the end user did not press the Return key.
The
RemoteServer program provides remotely accessible
send and
get methods. Fruit order clients call
send methods to send data to the server, and view order clients call the
get methods to retrieve the data. In this example, the server program has no user interface.
The
OrderClient program presents a user interface, and when the end user clicks
View Order, the program gets the order data from the server program and puts it on the screen.
See Part 1, Lesson 8: Remote Method Invocation, for information on how to run the example. Use the Part 1, Lesson 8 instructions, but use the source code provided in this lesson. Here is a summarized version of those steps:
Compile: These instructions assume development is in the
zelda home directory.
Unix:
cd /home/zelda/classes
javac Send.java
javac RemoteServer.java
javac RMIClient2.java
javac RMIClient1.java
rmic -d . RemoteServer
cp RemoteServer*.class /home/zelda/public_html/classes
cp Send.class /home/zelda/public_html/classes
Win32:
cd \home\zelda\classes
javac Send.java
javac RemoteServer.java
javac RMIClient2.java
javac RMIClient1.java
rmic -d . RemoteServer
copy RemoteServer*.class \home\zelda\public_html\classes
copy Send.class \home\zelda\public_html\classes
|
Start rmi Registry:
Unix:
cd /home/zelda/public_html/classes
unsetenv CLASSPATH
rmiregistry &
Win32:
cd \home\zelda\public_html\classes
set CLASSPATH=
start rmiregistry
|
Start Remote Server:
Unix:
cd /home/zelda/public_html/classes
java
-Djava.rmi.server.codebase=http://kq6py/~zelda/classes
-Djava.rmi.server.hostname=kq6py.eng.sun.com
-Djava.security.policy=java.policy RemoteServer
Win32:
cd \home\zelda\public_html\classes
java -Djava.rmi.server.codebase=
file:c:\home\zelda\public_html\classes
-Djava.rmi.server.hostname=kq6py.eng.sun.com
-Djava.security.policy=java.policy RemoteServer
|
Start RMIClient1:
Unix:
cd /home/zelda/classes
java -Djava.rmi.server.codebase=
http://kq6py/~zelda/classes/
-Djava.security.policy=java.policy RMIClient1
kq6py.eng.sun.com/~zelda
Win32:
cd \home\zeldzeldaa\classes
java -Djava.rmi.server.codebase=
file:c:\home\zelda\classes\
-Djava.security.policy=java.policy RMIClient1
kq6py.eng.sun.com\home\zelda\public\html
|
Start RMIClient2:
Unix:
cd /home/zelda/classes
java -Djava.rmi.server.codebase=
http://kq6py/~zelda/classes
-Djava.rmi.server.hostname=kq6py.eng.sun.com
-Djava.security.policy=java.policy RMIClient2
kq6py.eng.sun.com
Win32:
cd \home\zelda\classes
java -Djava.rmi.server.codebase=
file:c:\home\zelda\public_html\classes
-Djava.rmi.server.hostname=kq6py.eng.sun.com
-Djava.security.policy=java.policy RMIClient2
kq6py.eng.sun.com
|
The RMIClient1.java code uses label, text field, text area, and button components to create the user interface for ordering fruit.
On the display, user interface components are arranged in a 2-column grid with labels in the left column, and the input and output data fields (text fields and text areas) aligned in the right column.
The end user enters his or her apples, peaches, and pears order into the text fields and presses the Return key after each fruit entry. When the Return key is pressed, the text field behavior updates the item and cost totals displayed in the text areas.
The
Reset button behavior clears the display, and the underlying total cost and items variables. The
Purchase button behavior sends the order data to the server program. If the
Reset button is clicked before the
Purchase button,
null values are sent over the network.
These next lines declare the Project Swing component classes the
SwingUI class uses. These are instance variables that can be accessed by any method in the instantiated class. In this example, they are built in the
SwingUI constructor and accessed in the
actionPerformed method implementation.
JLabel col1, col2; JLabel totalItems, totalCost; JLabel cardNum, custID; JLabel applechk, pearchk, peachchk; JButton purchase, reset; JPanel panel; JTextField appleqnt, pearqnt, peachqnt; JTextField creditCard, customer; JTextArea items, cost; static Send send; int itotal=0; double icost=0; |
The constructor is fairly long because it creates all the components, sets the layout to a 2-column grid, and places the components in the grid on a panel. A panel is a container component that holds other components.
The
Reset and
Purchase buttons and the
appleQnt,
pearQnt, and
peachQnt text fields are added as action listeners. This means when the end user clicks one of the buttons or presses Return in one of the text fields, an action event occurs that causes the platform to call the
FruitClient.actionPerformed method where the behaviors for these components are defined.
As explained in
Part1, Lesson 4: Building a User Interface, a class declares the
ActionListener interface and implements the
actionPerformed method if it needs to handle action events such as button clicks and text field Returns. Other user interface components generate some different action events, and as a result, require you to implement different interfaces and methods.
//Create left and right column labels
col1 = new JLabel("Select Items");
col2 = new JLabel("Specify Quantity");
//Create labels and text field components
applechk = new JLabel(" Apples");
appleqnt = new JTextField();
appleqnt.addActionListener(this);
pearchk = new JLabel(" Pears");
pearqnt = new JTextField();
pearqnt.addActionListener(this);
peachchk = new JLabel(" Peaches");
peachqnt = new JTextField();
peachqnt.addActionListener(this);
cardNum = new JLabel(" Credit Card:");
creditCard = new JTextField();
customer = new JTextField();
custID = new JLabel(" Customer ID:");
//Create labels and text area components
totalItems = new JLabel("Total Items:");
totalCost = new JLabel("Total Cost:");
items = new JTextArea();
cost = new JTextArea();
//Create buttons and make action listeners
purchase = new JButton("Purchase");
purchase.addActionListener(this);
reset = new JButton("Reset");
reset.addActionListener(this);
|
JPanelThe example in
Part 1, Lesson 4: Building a User Interface, used the
BorderLayout layout manager. This example uses the
GridLayout layout manager, which arranges components in a grid or the number of rows and columns you specify. The example uses a 2-column grid with an unlimited number of rows as indicated by the zero (unlimited rows) and two (two columns) in the statement
panel.setLayout(new GridLayout(0,2));.
The layout manager and color are set on the panel, and the panel is added to the content pane with a call to the
getContentPane method of the
JFrame class. A content pane lets different types of components work together in Project Swing.
//Create a panel for the components panel = new JPanel(); //Set panel layout to 2-column grid //on a white background panel.setLayout(new GridLayout(0,2)); panel.setBackground(Color.white); //Add components to panel columns //going left to right and top to bottom getContentPane().add(panel); panel.add(col1); panel.add(col2); panel.add(applechk); panel.add(appleqnt); panel.add(peachchk); panel.add(peachqnt); panel.add(pearchk); panel.add(pearqnt); panel.add(totalItems); panel.add(items); panel.add(totalCost); panel.add(cost); panel.add(cardNum); panel.add(creditCard); panel.add(custID); panel.add(customer); panel.add(reset); panel.add(purchase); |
The
actionPerformed method provides behavior for each of the following possible application events:
Purchase or
Reset button.
appleQnt,
peachQnt, or
pearQnt field.
actionPerformedpurchasepearQntResetpurchasepearQnt Purchase Button: The
Purchase button behavior involves retrieving data from the text fields and text areas, and sending that data to the server program. The server program is available to the
FruitClient program through its
Send interface, which declares the remote server methods for sending and getting data.
The
send variable is an instance of the
Send interface. This instance is created in the
FruitClient program's
main method. The
send variable is declared
static and global in the
FruitClient program so the
static main method can instantiate it, and to make it accessible to the
actionPerformed method.
if(source == purchase){
cardnum = creditCard.getText();
custID = customer.getText();
apples = appleqnt.getText();
peaches = peachqnt.getText();
pears = pearqnt.getText();
try{
send.sendCreditCard(cardnum);
send.sendCustID(custID);
send.sendAppleQnt(apples);
send.sendPeachQnt(peaches);
send.sendPearQnt(pears);
send.sendTotalCost(icost);
send.sendTotalItems(itotal);
} catch (Exception e) {
System.out.println("Cannot send data to server");
}
}
|
pearQnt
if(source == pearqnt){
number = pearqnt.getText();
if(number.length() > 0){
pearsNo = Integer.valueOf(number);
itotal += pearsNo.intValue();
pearqnt.setNextFocusableComponent(creditCard);
} else {
itotal += 0;
pearqnt.setNextFocusableComponent(creditCard);
}
}
|
End users can use the Tab key to move the cursor from one component to another within the user interface. The default Tab key movement steps through all user interface components including the text areas.
Because the end user does not interact with the text areas, there is no reason for the cursor to go there. The example program includes a call in its constructor to
pearqnt.setNextFocusableComponent to make the cursor move from the
pearqnt text field to the
creditcard text field bypassing the total cost and total items text areas when the Tab key is pressed.
applechk = new JLabel(" Apples");
appleqnt = new JTextField();
appleqnt.addActionListener(this);
pearchk = new JLabel(" Pears");
pearqnt = new JTextField();
pearqnt.addActionListener(this);
peachchk = new JLabel(" Peaches");
peachqnt = new JTextField();
peachqnt.addActionListener(this);
cardNum = new JLabel(" Credit Card:");
creditCard = new JTextField();
//Make cursor go to creditCard component
pearqnt.setNextFocusableComponent(creditCard);
customer = new JTextField();
custID = new JLabel(" Customer ID:");
|
To calculate the items ordered and their cost, the string values retrieved from the
appleQnt,
peachQnt, and
pearQnt text fields have to be converted to their number equivalents.
The string value is returned in the
number variable. To be sure the user actually entered a value, the string length is checked. If the length is not greater than zero, the end user pressed Return without entering a value. In this case, the
else statement adds zero to the running total and the cursor focus is set for the
creditCard text field. Adding zero is not really necessary, but does make the code more understandable for someone reading it.
If the length is greater than zero, an instance of the
java.lang.Integer class is created from the string. Next, the
Integer.intValue() method is called to produce the integer (
int) equivalent of the string value so it can be added to the items total kept in the
itotal integer variable.
if(number.length() > 0){
pearsNo = Integer.valueOf(number);
itotal += pearsNo.intValue();
} else {
itotal += 0;
}
|
actionPerformedTo display the total items, a
java.lang.Integer object is created from the
itotal integer variable. The
Integer.toString method is called to produce the
String equivalent of the integer (
int). This string is passed to the call to
this.cost.setText(text2) to update the Total Cost field in the display.
Note: The
![]()
costtext area variable is referenced asthis.costbecause theactionPerformedmethod also has acostvariable of typeDouble. To reference the global text area and not the localDoubleby the same name, you have to reference it asthis.cost.
![]()
num = new Integer(itotal); text = num.toString(); this.items.setText(text); icost = (itotal * 1.25); cost = new Double(icost); text2 = cost.toString(); this.cost.setText(text2); |
intdoubleThe
int data type contains a single whole 32-bit integer value that can be positive or negative. You can use the standard arithmetic operators (+, -, *, and /) to perform arithmetic operations on the integer.
The
Integer class, not only contains a whole 32-bit integer value that can be positive or negative, but provides methods for working on the value. For example, the
Integer.intValue method lets you convert an
Integer to an
int to perform arithmetic operations.
The
double data type contains a 64-bit double-precision floating point value. The
Double class not only contains a 64-bit double-precision floating point value, but provides methods for working on the value. for example, the
Double.doubleValue method lets you convert a
Double to a
double to perform arithmetic operations.
The server program consists of the
RemoteServer.java class that implements the methods declared in the
Send.java interface. These classes are described in
Part 1, Lesson 8: Remote Method Invocation with the only difference being in this lesson there are many more
sendXXX and
getXXX methods to declare and implement. Here is the list:
The important thing to note is data of any type and size can be easily passed from one client through the server to another client using the RMI API. No special handling is needed for large amounts of data or special considerations for different data types, which can sometimes be issues when using socket communications.
The OrderClient.java class uses text areas and buttons to display the order information.
The code is very similar to the
FruitOrder.java class so rather than repeat much of what you have read above, this section highlights two parts of the
actionPerformed method behavior for viewing an order.
The first part retrieves the credit card number, and the number of apples, peaches, and pears ordered from the server and sets those values in the corresponding text areas.
The second part retrieves the cost and item totals, which are
double and
integer, respectively. It then converts the total cost to a
java.lang.Double object, and the total items to a
java.lang.Integer object, and calls the
toString method on each to get the string equivalents. Finally, the strings can be used to set the values for the corresponding text areas.
if(source == view){
try{
//Retrieve and display text
text = send.getCreditCard();
creditNo.setText(text);
text = send.getCustID();
customerNo.setText(text);
text = send.getAppleQnt();
applesNo.setText(text);
text = send.getPeachQnt();
peachesNo.setText(text);
text = send.getPearQnt();
pearsNo.setText(text);
//Convert Numbers to Strings
cost = send.getTotalCost();
price = new Double(cost);
unit = price.toString();
icost.setText(unit);
items = send.getTotalItems();
itms = new Integer(items);
i = itms.toString();
itotal.setText(i);
} catch (Exception e) {
System.out.println("Cannot send data to server");
}
}
|
The example program as it is currently written has two major design flaws in the fruit order client. The first one involves the need to press the Return key for calculations to happen, and the second involves handling the error condition if the end user enters a character that is not a number when ordering apples, peaches, and pears.
Calculations and Pressing Return: If the end user enters a value for apples, peaches, or pears and moves to the next field without pressing the Return key, no calculation is made. This means when the end user clicks the Purchase key, the order is sent, but the item and cost totals will be incorrect. So, in this particular application relying on the Return key action event is not good design.
Modify the
actionPerformed method so this does not happen. Here is one possible
solution. Give it a try before taking a look.
Non-Number Errors: If the end user enters a non-number value for apples, peaches, or pears the program will present a stack trace indicating an illegal number format. A good program will catch and handle the error, rather than produce a stack trace.
Hint: You need to figure out which part of the code throws the error and enclose it in a
try and
catch block.
try and
catch blocks were first introduced in
Part 1, Lesson 6: File Access and Permissions. The error you need to catch is
java.lang.NumberFormatException.
Give it a try before taking a look at the solution.
You can find more information on event listening in the Writing Event Listeners lesson in The Java Tutorial.
The Variables and Data Types trail in The Java Tutorial provides more information on primitive data types.
See The JFC Swing Tutorial: A Guide to Constructing GUIs for more information on Project Swing.
*As used on this web site, the terms "Java virtual machine" or "JVM" mean a virtual machine for the Java platform.
[ TOP]

