Chapter 10 -- The Order Entry System: Exception
Handling and Browser Interaction
Chapter 10
The Order Entry System: Exception
Handling and Browser Interaction
CONTENTS
Many languages do not have built-in capabilities to allow you
to detect and deal with errors and mishaps efficiently. Luckily,
Java gives you ways to handle these problems simply and effectively.
This chapter explores the process of handling exceptions and errors.
In other words, you'll plan on a certain progression through your
code, but you also will implement code that will cover situations
when things don't go your way. One such instance of when things
don't go right generates an exception called ClassNotFoundException.
This, of course, is generated when the runtime looks for a class
and cannot find it.
Different types of mishaps are defined in the Java libraries,
each in separate classes. Each of these separate classes describes
what kind of mishap occurs. You also can define your own Exception
classes to customize how you are going to deal with something
that goes awry in your program.
Handling exceptions and errors accomplishes several things. First,
you want to minimize data loss. Also, you want to alert the user
that something has gone wrong and try to specify exactly what
went wrong as much as possible. You want get out of the program
as cleanly as possible and minimize the effect this process may
have on other applications or processes.
This chapter covers in-depth these concepts and the command structures
to implement them.
This chapter also explores how you can get your applets to communicate
and interact with the browser displaying them. You can instruct
the browser to load and display a different URL, for example.
The process of interacting with the browser also is covered in
depth in this chapter.
Finally, you will finish up the Order Entry System in this chapter.
You will add the capability to interact with the browser. You
also will learn the ways you can get the information in the applet
back to your server. A complete final listing is included at the
end of this chapter.
Why should you use exceptions and error handling? The following
code structure should look familiar to you if you have ever tried
to "home-brew" some code to deal with what now are called
exceptions:
int errcode = goGetaFile();
if (err != ALLOK) {
// deal with things. .
} else {
// we're cool . .
}
What's wrong with this? Well, a number of things. First, you have
to recode the method used to deal with a certain type of mishap
over and over. But suppose that you implement a function to handle
this. So, for every different error type, you'll need to create
a different function to handle the error. Second, you cannot always
return an error code from a function. What if you want to handle
errors that might result from a function that returns an integer?
How would you set which value specifies an error? What if you
have nested procedures or method calls? How are you going to deal
with saving the data saved in higher level classes? The answer
is that you can't. There must be a better way, and there is.
Error and exception classes, as defined in Java,
enable you to safely and easily deal with situations in which
you want to handle errors and abnormal occurrences. Suppose that
your program calls a nonexistent method in another class, or an
image cannot be loaded; these are different types of exceptions.
An example of a Java error is the OutofMemoryError,
which is an error resulting from a lack of necessary free memory
space.
The goal of this whole process is to remove the kind of home-brewed
code demonstrated earlier in this section. It should enable you
to develop an easy way to identify when mishaps occur and then
specify another handler function to deal with them. When an exception
or error occurs, your code throws an instance of the class that
defines it. It then is caught by another segment of code designed
to deal with the mishap.
Note: |
If you have any Ada or C++ programming experience, the exception-handling format discussed later in this chapter should be pretty familiar to you. Java is designed to extend and simplify exception and error handling. Ada has five exception classes, for
example, whereas Java has more than three times that. C++ has only two types of exception classes. You also will notice that Java divides exceptions that normally are grouped into one category in other languages into two groups: exceptions and
errors.
|
Both errors and exceptions are implemented in library classes
that descend from the class Java.lang.Throwable.
Figure 10.1 shows the inheritance path of the Exception
and Error classes in the
java.lang package.
Figure 10.1: The inheritance of the Exception and Error classes. Noice that both are descendants of the Throwable class.
Different types of exceptions and errors are extensions of these
two classes. The available Java exceptions follow:
ArithmeticException
ArrayIndexOutOfBoundsException
ArrayStoreException
ClassCastException
ClassNotFoundException
CloneNotSupportedException
IllegalAccessException
IllegalArgumentException
IllegalMonitorStateException
IllegalThreadStateException
IndexOutOfBoundsException
InstantiationException
InterruptedException
NegativeArraySizeException
NoSuchMethodException
NullPointerException
NumberFormatException
RuntimeException
SecurityException
StringIndexOutOfBoundsException
The available Java Error
classes follow:
AbstractMethodError
ClassCircularityError
ClassFormatError
IllegalAccessError
IncompatibleClassChangeError
InstantiationError
InternalError
LinkageError
NoClassDefFoundError
NoSuchFieldError
NoSuchMethodError
OutOfMemoryError
StackOverflowError
UnknownError
UnsatisfiedLinkError
VerifyError
VirtualMachineError
Why the difference between exceptions and errors? The organizational
difference is needed because of the ways the different types need
to be handled. Errors and the classes that derive from the Error
class result from errors inside the system, such as lack of memory
or some other error beyond your control. The idea in these instances
is just to keep your program from crashing hard and simply to
exit cleanly or figure a way around the problem. For this reason,
your programming will not have to deal with these thrown Errors,
because they usually are implemented by other classes that make
sure those kind of errors don't occur and are handled nicely (instead
of, for example, locking up the machine or crashing the operating
system). In other words, you don't need to worry about handling
OutofMemoryErrors, StackOverflowErrors
and so on; they generally already are handled for you.
You can concentrate on handling the different types of exceptions
that can rear their ugly heads during your programs. Runtime exceptions
normally result from your own coding mistakes. For this reason,
you should plan on incorporating this process of exception handling
in order to cover for your own mistakes. This makes for much more
effective and robust code.
Note: |
Error handling and exception handling are implemented by the same process. They are both thrown and caught. Situations in which you will need to handle errors are very rare. Runtime exceptions are your main concern, because they are usually your fault. A
number of other exceptions are available, such as ClassNotFoundException or IOException, which you may want to use only as a means to prompt the user that something in his installation or setup of your program is wrong. If you notice when
you try to load an applet that is specified by your html document but isn't there, a ClassNotFoundException is reported by Netscape.
|
What if you could just say, in an easily understood format, "Hey,
I want you to try and do this stuff here and if anything goes
wrong with any of the code, I want you to execute this code here
to handle it." Well, that is exactly what happens in the
case of handling exceptions and errors.
Four words are reserved in Java to enact the handling of Throwable
objects. Remember that exceptions and errors are both descendants
of the Throwable class. These
four words are try, catch,
finally, and throw.
To implement exception handling around one specific block of code,
the words try and catch
are positioned in the following structure:
try {
// Some code that might throw an exception.
.
}
catch (SomeException EX)
{
// Do something appropriate in response
. .
}
So what's going on in this segment? Well, the statement says,
"OK, I want you to try
this code here and if anything in there throws an exception, the
catch statements coming up
are going to figure out what to do." If you are accessing
something using the URL for that location, for example, you can
use this code:
try {
// Doing something with a URL . .
}
catch (MalformedURLException EX) {
// Do something appropriate to deal with
the problem . .
}
You also can catch multiple exceptions by using a try
statement:
try {
// Doing something . .
.
.
.
}
catch (MalformedURLException EX) {
// Do something appropriate to deal with
the problem . .
}
catch (Exception E) {
// Do something appropriate to deal an
exception in general . .
}
If some method or statement executed in the try
block throws an exception, it is caught by the catch
statement, which accepts the appropriate exception type and then
executes the code inside its block.
Suppose that you want some code to be executed no matter what
happens in the try statement.
You can use the finally clause
after your try/catch
block:
try {
// Some code that might throw an exception
. .
}
catch (SomeException SE) {
// What to do if some exception is thrown.
. .
} finally {
// I want you to do this no matter what,
if things go wrong or right.
}
What happens? The code in the try
block is executed. If some exception is thrown, the catch
statement deals with it. Whether things go right or wrong, the
code in the finally block
executes.
This code is useful, for example, if you are modifying a file
on disk and you want the file to revert back to its old state
without keeping any changes, regardless of what happens. The finally
block includes the code (or a call to a method) to close the file
and then copies the backup you designated as the main file.
The code also is useful if you are in the process of transmitting
data across a network, for example. Even if everything goes right
or something goes wrong, you want to alert the other computer
that it should not be expecting any more data from you. The following
code represents this process:
try {
// Transmit data . .
}
catch (Error E) {
System.out.print("Error " +
E + " resulted.")
}
catch (Exception E) {
System.out.print("Exception "
+ E + " resulted.");
}
finally {
// Tell the other computer the transmission
is over . .
}
It is important to know that as soon as code in the try
block generates any class descendant from Throwable,
the execution of the code stops. If the thrown class is handled
in the following catch, it
is handled there. Otherwise, it propagates up the class line.
To reiterate, when something is thrown by code in a try
block, the execution of that code is halted immediately.
Note: |
When catching exceptions or errors, when you specify one type of exception or error, that catch statement will catch that class along with every descendant class. For example, you might use the following code:
catch (Throwable T) {
This will deal with everything that throws any instance of the Throwable class, along with every descendant of the Throwable class (remember the Throwable inheritance hierarchy in Figure 10.1).
Suppose that you use this code:
catch (Exception E) {
This catches instances of the Exception class, along with every descendant of that class.
|
It is apparent that other classes and their methods throw exceptions,
so you also want your own code and classes to be able to throw
them. To throw an exception called EX,
for example, you simply insert the following:
throw EX;
If you place this statement in a try
block, you can catch the exception you just threw in the catch
block following it:
AnException EX = new AnException();
try {
// Something bad happens. .
throw FX;
}
catch (AnException AnotherFX) {
// Do something about it . .
}
Why would you want to do this? Suppose that you want to do something
if a certain function returns a value of 0. You use that function
in the try block, and then,
if the value returned is 0, you throw the ZeroValueException.
Then you can catch it in the catch
block and deal with it accordingly.
Suppose that you want to have your own class or a method throw
exceptions. You would define your class as the following:
public class ThrowSomething throws SomeException
{
By adding the throws to the class or method definition, you alert
other classes or methods that use it that they should expect the
possibility of having to catch some kind of exception from your
class's execution. You also can specify that you want to alert
everyone else that you might want to throw more than one type
of exception. To do this, simply separate multiple exception types
in the declaration with commas. The following class might throw
a SomeException class or
an AnotherException class:
public class ThrowTwoSomethings throws
SomeException, AnotherException {
Note: |
Class declarations can get pretty heavy-duty in Java. The following is a valid declaration:
public class CrazeeDeclaration throws SomeException, AnException extends Applet implements Runnable {
This declares a class, CrazeeDeclaration, which can throw some exception types, is an extension of the Applet class, and implements Runnable (a declaration dealing with threads, which is covered in Chapter
16, "Multithreading with Java").
|
Tip: |
Don't set all your classes and methods to throw errors and RuntimeExceptions, or any of their descendants. All the RuntimeExceptions or any of the Error class and their descendants are handled already without your intervention.
You simply don't have to worry about them.
|
To specify when to throw an exception, insert the throw clause
inside a class that throws an exception type. The following class
demonstrates this:
public class SomeSuckerClass throws SomeException
{
// Do some stuff . .
// More stuff . .
// If something went wrong . .
If (CurrentValue == BadValue) {
SomeException
SE = new SomeException ();
throw(SE);
}
}
What happens? The code is acted on, and then if some bad thing
happens that you want to throw an exception for, you create a
new instance of your extension of the Exception
class and then throw it. At that point, the code execution stops,
the exception is thrown, and it travels up the hierarchy until
it is handled. The execution does not come back to your
code, so you should expect that when you throw an exception or
an error class, you aren't coming back to execute the next line
of code.
So, to sum things up, you simply alert the world that you are
going to throw an exception through the throw
clause. Then you create an instance of an exception and you throw
it.
At times, you will want to throw your own exceptions. On these
occasions, you declare your own extension of the Exception
class. Notice that this was used previously when you threw an
instance of AnException.
The details of creating your own exception classes are covered
in the next section.
Why do you want to declare your own instances of the Exception
class? Well, there are a couple of reasons. First, if you have
an exception that isn't handled adequately by any of the standard
library exceptions, you can declare your own. Second, it enhances
readability. But be sure not to go overboard in creating exceptions,
because they easily clutter your code.
To create your own exception, simply extend the exception type
or any of its descendants. Then create constructors for your class:
public class MyVeryOwnException extends
Exception {
// The constructor.
MyVeryOwnException () {
}
MyVeryOwnException (String message) {
super(message);
}
}
Note: |
Why the second constructor? It is typical practice for the descendants of the Throwable class to allow a message to be included in the class. To include a message when you declare an instance of a Throwable class (or one of its
descendants), simply send a message as a parameter when you declare the class. The following code declares a MalFormedURLException and sets the message:
MalFormedURLException MFURLE = new MalFormedURLException("We're getting killed here!");
To retrieve the message, you can use this code:
AString = MFURLE.getMessage();
This places the message contained in the MFURLE class into the string AString.
|
The first place you'll use exceptions is in the UpdateValues
method. You might remember that the UpdateValues
method is called whenever a change is made to the User Interface
values. It recomputes the new price per item, the subtotal, and
the total displayed by the applet. Listing 10.1 shows the updateValues
method of the Order Entry System without the exception handling
you will be adding.
Listing 10.1. The UpdateValues
void code listing.
/* This void
will change all of the values to match any changes
in the input settings. First,
it declares a number of variables
local to the method. Then,
it sets a modifier variable and a
base price variable depending
on which items are selected in the
choice box, the list, and
the slider. Then, it inserts those
values onto the applet panel.
*/
private void updateValues() {
// The index of the selected size.
int
WhichChoice = SizeChoice.getSelectedIndex();
// The amount of items desired.
int AmountSelected = OrderAmountSlider.getValue();
// The index of the selected product.
int WhichProduct = ProductList.getSelectedIndex();
/* The initial base price and modifier. Remember,
the modifier is the amount
the base price is multiplied
by to get the price per item.
*/
double CurrentBasePrice = 0.0;
double CurrentModifier = 0.0;
/* This switch statement compares the
index of the product
list, held in WhichProduct,
and sets the inital
BasePrice accordingly.
*/
switch (WhichProduct) {
case
0:
CurrentBasePrice
= ProdOneBaseValue;
break;
case 1:
CurrentBasePrice
= ProdTwoBaseValue;
break;
case 2:
CurrentBasePrice
= ProdThreeBaseValue;
break;
case 3:
CurrentBasePrice
= ProdFourBaseValue;
break;
}
/* This switch statement compares the
WhichChoice variable
(which is the selected index
in the sizeChoice choice
box) to the different indexes. And
then sets the modifier
accordingly.
*/
switch (WhichChoice) {
case
3:
CurrentModifier
= multiplierSmall;
break;
case 2:
CurrentModifier
= multiplierMedium;
break;
case 1:
CurrentModifier
= multiplierLarge;
break;
case 0:
CurrentModifier
= multiplierJumbo;
break;
}
// Insert the
number on the slider to the applet.
AmountLabel.setText(Integer.toString(AmountSelected)+
" ");
// Compute the
price per item and insert it onto the applet panel.
double PricePerItem
= (CurrentBasePrice*CurrentModifier);
PricePerItemLabel.setText(Double.toString(PricePerItem)+
" ");
// The subtotal
is the number ordered times the price per item.
double SubTotal
= (CurrentBasePrice*CurrentModifier*AmountSelected);
// Insert the
subtotal onto the applet panel.
SubTotalLabel.setText(Double.toString(SubTotal)+
" ");
/* Since the total
is the same as the subtotal
(cause
we only have one item to be ordered
at
a time), we can simply use the value in
the
subtotal.
*/
TotalLabel.setText(SubTotalLabel.getText());
}
If you examine the Order Entry System so far, you'll have a hard
time finding instances that just scream Use exception handling
here! So, you'll create one that will make for a simple example.
One thing that you might want to look for is that the AmountSelected
is not 0. If it is 0, you don't really need to update the values.
You can implement your own version of exception and have the updateValues
method throw it to signify that the value is 0.
Note: |
Using exceptions in this case is a bad idea since they are completely unnecessary. You should use exceptions in much more important areas such as dealing with input and output or network connections.
|
The first step is to define your own Exception
class. You'll simply extend the Exception
class in general:
Exception ZeroValueException = new Exception
("Zero Value Encountered.");
You will place this in the updateValues
method itself. Then you'll say that the updateValues
method possibly will throw an instance of your new exception.
This will be done by changing the class-method declaration for
the updateValues method.
The new declaration for the method follows:
public void updateValues throws Exception
{
So, the next step is that if you come across a 0 value for the
AmountSelected, you will
throw the ZeroValueException
you created before by saying this:
if (AmountSelected == 0) {
throw(ZeroValueException);
}
This throws your exception and jumps out of the method right there
before anything is computed.
Finally, you'll need to have code to handle the exception you
are throwing. To do this, you'll add a try/catch
block around the calling of the updateValues
method in the action and
handleEvent methods of the
Order Entry System applet. To do this, you'll use this code:
try {
updateValues();
}
catch (Exception E) {
System.out(E.getMessage());
}
This simply tries the updateValues()
method and then catches any instances of descendants of the Exception
class that are thrown.
This (unproductive) addition to the Order Entry System is included
in Listing 10.2. The code changes are shown in bold
type.
It would be a waste to simply have your applets be static and
encapsulated programs inside a browser. Java is designed to allow
your applets to communicate with the browser and with each other.
Suppose that you want to get information in one applet and display
it to another applet to be displayed. Or, you might want to tell
the browser to display another Web page or load and play an audio
clip. The next section tells you how to do these things.
The AppletContext interface
is an interface designed to let applets communicate with the browser.
Table 10.1 summarizes the methods available to you as part of
the AppletContext interface.
Table 10.1. Methods available in the AppletContext
interface.
Method | Function
|
Applet getApplet(String name);
| Gets an applet named name. If it can't find it, null is returned.
|
AudioClip getAudioClip(URL url);
| Gets an audio clip at URL url.
|
Enumeration getApplet();
| Lists the applets available in the current context. In other words, the list of those currently displayed.
|
Image getImage(URL url);
| Gets an image at URL url.
|
public void showDocument (URL url, String target);
| Shows a new document in a target window or frame. This may be ignored. Accepts the target strings: _self:show in current frame, parent:show in parent frame, top:show in top-most frame,
blank:show in new unnamed top-level window, and <other>:show in new top-level window named <other>.
|
void showDocument(URL url);
| Tells the browser to show a document at URL url. Note: This may be ignored.
|
void showStatus(String status);
| Sets the status string shown. |
These methods are all implemented by the different browsers that
can display Java applets. Notice that some of the interface methods
can be ignored by the browser at their discretion. You should
plan your applets accordingly. To find out how specific browsers
treat the optional methods is a trial and error process. The extent
to which these methods are implemented by each browser is dependent
upon the manufacturer's preference.
So how do you implement these methods? Suppose that you want your
applet to get an image at a specific URL. You can use this code
to load an image and then store it in the Image
class:
Image NetImage = getImage(url);
Note: |
For more information on the URL class, see Chapter 12, "Network Programming with Java."
|
If you want to tell the browser to load another document contained
at URL
http://mega.dinky.com/~girdleyj/a.html
you can use this code:
URL aURL = new URL("http://mega.dinky.com/~girdleyj/a.html");
getAppletcontext().showdocument(aurl);
This constructs a new instance of the URL
class and then sets it. The next line then tells the browser to
show that document at the URL specified.
Another version of the showDocument
method is available. As summarized before, it takes this form:
getAppletContext().showDocument (URL
aURL, String Target);
The URL specified tells the
browser which document to load. Target
tells the browser where to put it. You can tell the browser to
display the document and those constants in many places (refer
to Table 10.1). The most powerful of these constants are those
that allow you to tell the browser to create a new frame, which
can be a frame inside of a viewer or a new window itself.
Suppose that you want to tell the browser to display a document
in the current frame. You can use this code:
getAppletContext().showDocument (aURL,
"_self");
If you want to create a new browser window named Billy, you can
use this code:
getAppletContext().showDocument (aURL,
"Billy");
And it's just that easy. Figure 10.2 shows the output from the
Netscape 3.0 when displaying an applet that instructs the browser
to display a new window with another html file. In this case,
the new window simply displays a junk text file.
Figure 10.2. : The output from telling the browser to open a new windows using the show Document command
You'll use this feature to call up a new browser window that displays
a help file in html format. You'll add this later in the chapter
when you update the Order Entry System.
Note: |
Why do some of the interface methods require that you first specify the getAppletContext() method before you can use them? Well, if you look at the actual implementation of the Applet class, you will notice that sometimes you can simply
just use these functions from the AppletContext interface without specifying the interface itself, because they are declared again by the Applet class. To use the showDocument method in general, for example, you can use this
code:
getAppletContext().showDocument(. . . );
If you are unable to get a method to work that you know is in the interface, you might want to try this code to call it directly instead of going through the applet itself.
|
Using Parameters in Applets |
The java.awt.Applet class specifies a method called getParameter, which allows you to get parameters specified in the html document containing your applet. The parameters are referenced by name.
See Chapter 5, "Writing a Java Applet: The Order Entry System," to learn how to specify parameters for your applets.
The getParameter function returns a string that is the value sent in. Suppose that you have the following applet declaration:
<APPLET CODEBASE = "http://Madeup.com/" CODE = "YourMama.class" WIDTH = 100 ÂHEIGHT = 50>
<PARAM NAME = Pone value="1">
<PARAM NAME = Asd value = "Jack Dempsey">
</APPLET>
To retrieve the value stored in parameter Pone, you can use this code:
String InPone = getParameter ("Pone");
Notice that the parameter is always a string. If you want to send in values, you must convert the string to an integer. You can do this by using the Integer class, which is a wrapper for the integer type that provides different utility functions
to deal with integers. One such method is the ParseInt function, which enables you to parse a string and return an integer. If you want to get the value stored in the Pone parameter, for example, you can use this code:
AnInt = Integer.parseInt(InPone);
This places the number in the InPone variable into the AnInt integer. Easy. This feature is useful, for example, if you are making an applet in which you want to allow users implementing it to have different choices for the colors,
borders, and so on for your applet without creating a new version for each combination of choices.
|
This chapter set a couple of goals for improving the Order Entry
System with the concepts presented here. First, you'll set things
so that an "about" document describing the Order Entry
System appears in a new window after the Order button is clicked,
as shown in Figure 10.3.
Figure 10.3. : The final appearance of the Order Entry System with separate windows function added.
You will use the showDocument
method in the AppletContext
interface. The showDocument
method accepts an instance of the class URL
and then displays it in a target you specify. First, you'll want
to create your own instance of the URL
class that points to the about.html file. Use this code:
try {
URL HelpURL = new URL (getDocumentBase(),
"about.html");
} catch (Exception e) {
System.out.print(e.getMessage());
}
Why the try statement? Well,
the constructor for the URL
class might throw an exception, so you have to deal with it. If
there is a problem, you need to catch the exception and deal with
it appropriately.
Next, you need to tell the browser to display that document at
that URL:
getAppletContext().showDocument(HelpURL);
And that's it. The new browser window loads with the about.html
document displayed.
You also will want to implement the (frivolous) exception handling
that was described previously in the final version.
Listing 10.2 shows the final version of the Order Entry System,
with the changes made in this chapter displayed in bold
type.
Listing 10.2. The Order Entry System Revisited.
import java.awt.*;
import java.applet.*;
import java.net.*;
public class OrderEntrySystem extends Applet {
OrderEntryFrameType OESFrame;
Button Order = new Button("Click
to Order");
Image ProductImage;
public void init() {
add(Order);
}
public boolean handleEvent(Event InEvent)
{
// Load
the logo image. .
Image
LogoInApplet = getImage(getDocumentBase(), "OESLogo.gif");
if (InEvent.target
== Order) {
Order.disable();
//
Try to create a new URL . .
try
{
URL
HelpURL = new URL (getDocumentBase(), "about.html");
//
Show the applet in a new window. .
getAppletContext().showDocument(HelpURL,
"About
the Order Entry System");
}
catch (Exception e) {
System.out.print(e.getMessage());
}
//
Display the new window . .
OESFrame
= new OrderEntryFrameType("Order Entry System");
OESFrame.resize(430,500);
OESFrame.setup(LogoInApplet);
OESFrame.show();
}
return super.handleEvent(InEvent);
}
}
class OrderEntryFrameType extends Frame {
OrderEntryFrameType (String InTitle) {
// Call the Frame
constructor . .
super(InTitle);
// Set the background
color for the Applet frame. .
setBackground(Color.white);
}
WarningDialog WDialog = new WarningDialog(this,
"You have not entered a name. ");
Panel Pan = new Panel();
public void setup(Image LogoInApplet)
{
// Set the initial
grid bag layout for the frame.
GridBagLayout
PrimaryLayout = new GridBagLayout();
setLayout(PrimaryLayout);
// Declare the
constraints for the Logo.
GridBagConstraints
LogoConstraints = new GridBagConstraints();
// Construct the
new canvas. .
LogoCanvas Logo
= new LogoCanvas(LogoInApplet);
LogoConstraints.gridwidth
= GridBagConstraints.REMAINDER;
// Set the constraints
for the logoinApplet.
PrimaryLayout.setConstraints(Logo,
LogoConstraints);
// Add the logo
canvas to the applet face.
add(Logo);
// Declare the
constraints for the Logo.
GridBagConstraints
hbarConstraints = new GridBagConstraints();
// Construct the
new canvas. .
HorizBar ProdBar
= new HorizBar("Product", 425);
// Say that we
want the logo to be the last thing on the line.
hbarConstraints.gridwidth
= GridBagConstraints.REMAINDER;
// Set the constraints
for the logoinApplet.
PrimaryLayout.setConstraints(ProdBar,
hbarConstraints);
// Add the logo
canvas to the applet face.
add(ProdBar);
// Declare and
initialize the product panel.
Panel ProductPanel
= new Panel();
// Set the layout
for the product panel and set the constraints for
// the components
inside of the product panel.
GridBagLayout
ProductPanelLayout = new GridBagLayout();
GridBagConstraints
InProductPanelConstraints =
new GridBagConstraints();
ProductPanel.setLayout(ProductPanelLayout);
// Here we will
set the list panel, which will hold the
// list choice
method and insertion.
Panel ListPanel
= new Panel();
ListPanel.setLayout(new
BorderLayout());
Label ProductLabel
= new Label("Products");
ListPanel.add("North",
ProductLabel);
// Create the
list, 4 items visible, no multiple
// selections.
ProductList =
new List(4, false);
// AddItems to
the List.
ProductList.addItem("Oscar");
ProductList.addItem("Lionhead");
ProductList.addItem("Jack
Dempsey");
ProductList.addItem("Angelfish");
// Add the List
to the list panel.
ListPanel.add("Center",ProductList);
// Add the imbedded
panel to the product panel.
InProductPanelConstraints.anchor
= GridBagConstraints.NORTH;
ProductPanelLayout.setConstraints(ListPanel,
InProductPanelConstraints);
ProductPanel.add(ListPanel);
// Another panel
which will be imbedded in the product panel.
Panel SizePanel
= new Panel();
SizePanel.setLayout(new
BorderLayout());
// Add a label
to the choice of sizes.
SizePanel.add("North",
new Label("Size:"));
// Create the
Choice box.
SizeChoice = new
Choice();
// AddItems to
the List.
SizeChoice.addItem("Jumbo");
SizeChoice.addItem("Large");
SizeChoice.addItem("Medium");
SizeChoice.addItem("Small");
// Add the Choice
to the Applet panel.
SizePanel.add("Center",SizeChoice);
// Add the imbedded
panel to the product panel.
ProductPanelLayout.setConstraints(SizePanel,
InProductPanelConstraints);
ProductPanel.add(SizePanel);
// Another
panel that will be imbedded in
the
product panel.
Panel AmountPanel
= new Panel();
AmountPanel.setLayout(new
BorderLayout());
// Add a label
to the slider.
AmountPanel.add("North",
new Label("Amount:"));
// Another
imbedded panel that will contain
the
slider and the output label.
Panel SliderPanel
= new Panel();
SliderPanel.setLayout(new
FlowLayout());
// Insert the
label that says how many are to be ordered
// of the item.
SliderPanel.add(AmountLabel);
// Create a vertical
slider, initial value of 0,
// minimum value
of 0, maximum value of 144.
OrderAmountSlider
= new
Scrollbar(Scrollbar.HORIZONTAL,
0, 0, 0, 144);
// Insert the
slider to the Applet panel.
SliderPanel.add(OrderAmountSlider);
AmountPanel.add("Center",
SliderPanel);
// Add the imbedded
panel to the product panel.
ProductPanelLayout.setConstraints(AmountPanel,
InProductPanelConstraints);
ProductPanel.add(AmountPanel);
// The last panel
that will be imbedded in the product panel.
Panel TotalPanel
= new Panel();
TotalPanel.setLayout(new
BorderLayout());
// Add the subtotal
label and a label saying that it is the subtotal.
TotalPanel.add("North",
new Label("Total: "));
TotalPanel.add("South",TotalLabel);
ProductPanelLayout.setConstraints(TotalPanel,
InProductPanelConstraints);
ProductPanel.add(TotalPanel);
// Add the imbedded
panel to the product panel.
ProductPanelLayout.setConstraints(TotalPanel,
InProductPanelConstraints);
ProductPanel.add(TotalPanel);
// Set the
constraints for the product panel,
which
will contain product choices, size, etc.
GridBagConstraints
ProductPanelConstraints = new GridBagConstraints();
// The product
panel will take up the rest of the space on this line.
ProductPanelConstraints.gridwidth
= GridBagConstraints.REMAINDER;
// Set the constraints
for the product panel's insertion.
PrimaryLayout.setConstraints(ProductPanel,
ProductPanelConstraints);
// Add the product
panel to the frame.
add(ProductPanel);
// Construct the
new canvas. .
HorizBar InfoBar
= new HorizBar("Your Information", 425);
// Say that we
want the logo to be the last thing on the line.
hbarConstraints.gridwidth
= GridBagConstraints.REMAINDER;
// Set the constraints
for the logoinApplet.
PrimaryLayout.setConstraints(InfoBar,
hbarConstraints);
// Add the logo
canvas to the applet face.
add(InfoBar);
// The second
panel to be imbedded in the frame is the info panel.
// This panel
gets the information about the user.
GridBagLayout
InfoPanelLayout = new GridBagLayout();
Panel InfoPanel
= new Panel();
GridBagConstraints
InfoPanelConstraints = new GridBagConstraints();
InfoPanelConstraints.gridwidth
= GridBagConstraints.RELATIVE;
InfoPanel.setLayout(InfoPanelLayout);
GridBagConstraints
InInfoConstraints = new GridBagConstraints();
InInfoConstraints.gridwidth
= GridBagConstraints.REMAINDER;
InInfoConstraints.anchor
= GridBagConstraints.WEST;
Label InfoLabel
= new Label("Your information: ");
InfoPanelLayout.setConstraints(InfoLabel,
InInfoConstraints);
InfoPanel.add(InfoLabel);
// The name entry
field area.
Panel NameFieldPanel
= new Panel();
NameFieldPanel.setLayout(new
BorderLayout());
NameFieldPanel.add("West",new
Label("Name:"));
NameFieldPanel.add("East",NameEntryField);
InInfoConstraints.anchor
= GridBagConstraints.EAST;
InfoPanelLayout.setConstraints(NameFieldPanel,
InInfoConstraints);
InfoPanel.add(NameFieldPanel);
// The Street
entry area implementation.
Panel StreetFieldPanel
= new Panel();
StreetFieldPanel.setLayout(new
BorderLayout());
StreetFieldPanel.add("West",new
Label("Street:"));
StreetFieldPanel.add("East",StreetEntryField);
InfoPanelLayout.setConstraints(StreetFieldPanel,
InInfoConstraints);
InfoPanel.add(StreetFieldPanel);
Panel CityFieldPanel
= new Panel();
CityFieldPanel.setLayout
= new BorderLayout());
CityFieldPanel.add("West",new
Label("City:"));
CityFieldPanel.add("East",CityEntryField);
InfoPanelLayout.setConstraints(CityFieldPanel,
InInfoConstraints);
InfoPanel.add(CityFieldPanel);
// The zip entry
field implementation.
Panel ZipFieldPanel
= new Panel();
ZipFieldPanel.setLayout(new
BorderLayout());
ZipFieldPanel.add("West",new
Label("Zip:"));
ZipFieldPanel.add("East",ZipEntryField);
InfoPanelLayout.setConstraints(ZipFieldPanel,
InInfoConstraints);
InfoPanel.add(ZipFieldPanel);
PrimaryLayout.setConstraints(InfoPanel,
InfoPanelConstraints);
// Add the info
panel to the frame layout.
add(InfoPanel);
Panel CommentPanel
= new Panel();
GridBagLayout
CommentPanelLayout = new GridBagLayout();
GridBagConstraints
CommentPanelConstraints =
new
GridBagConstraints();
CommentPanelConstraints.gridwidth
= GridBagConstraints.REMAINDER;
CommentPanel.setLayout(CommentPanelLayout);
GridBagConstraints
InCommentConstraints = new GridBagConstraints();
// The comment
label.
InCommentConstraints.anchor
= GridBagConstraints.WEST;
InCommentConstraints.gridwidth
= GridBagConstraints.REMAINDER;
Label CommentLabel
= new Label("Comments: ");
CommentPanelLayout.setConstraints(CommentLabel,
InCommentConstraints);
CommentPanel.add(CommentLabel);
// Add the comment
box.
InCommentConstraints.anchor
= GridBagConstraints.CENTER;
InCommentConstraints.gridwidth
= GridBagConstraints.REMAINDER;
CommentPanelLayout.setConstraints(CommentTextArea,
InCommentConstraints);
CommentPanel.add(CommentTextArea);
PrimaryLayout.setConstraints(CommentPanel,
CommentPanelConstraints);
// Add the info
panel to the frame layout.
add(CommentPanel);
// Add and create
the repeat customer checkbox.
Panel ContactPanel
= new Panel();
ContactPanel.setLayout(new
BorderLayout());
// Add a label
to the ContactMethodGroup.
ContactPanel.add("North",new
Label("How
would you like to be contacted? "));
// Declare the
checkbox group, and allocate space.
CheckboxGroup
ContactMethodGroup;
ContactMethodGroup
= new CheckboxGroup();
// Create some
checkboxes to put in the group.
Checkbox EmailBox
= new Checkbox("Email",ContactMethodGroup,true);
Checkbox PhoneBox
= new
Checkbox("Phone",ContactMethodGroup,false);
Checkbox MailBox
= new
Checkbox("US
Mail",ContactMethodGroup,false);
// Add the checkboxes
into the applet panel.
ContactPanel.add("West",EmailBox);
ContactPanel.add("Center",PhoneBox);
ContactPanel.add("East",MailBox);
// Sets the constraints
for the contact panel.
GridBagConstraints
ContactPanelConstraints =
new GridBagConstraints();
ContactPanelConstraints.gridwidth
= 2;
ContactPanelConstraints.weightx
= 2.0;
PrimaryLayout.setConstraints(ContactPanel,
ContactPanelConstraints);
add(ContactPanel);
// Insert the
different checkboxes into the panel.
GridBagConstraints
CustCheckBoxConstraints = new GridBagConstraints();
CustCheckBoxConstraints.weightx
=1.0;
CustCheckBoxConstraints.gridwidth
= GridBagConstraints.REMAINDER;
Checkbox RepeatCustCheckBox
= new Checkbox("Repeat Customer?");
PrimaryLayout.setConstraints(RepeatCustCheckBox,
CustCheckBoxConstraints);
add(RepeatCustCheckBox);
// Construct the
new canvas. .
HorizBar ButtonBar
= new HorizBar("Commands", 425);
// Set the constraints
for the logoin applet.
PrimaryLayout.setConstraints(ButtonBar,
hbarConstraints);
// Add the logo
canvas to the applet face.
add(ButtonBar);
GridBagConstraints
ButtonConstraints = new GridBagConstraints();
ButtonConstraints.gridx
= GridBagConstraints.RELATIVE;
// Spreads the
buttons out across the window.
ButtonConstraints.weightx
= 1.0;
ButtonConstraints.weighty
= 1.0;
// Declare, set,
and add the "Submit" button.
SubmitButton =
new Button("Submit");
PrimaryLayout.setConstraints(SubmitButton,
ButtonConstraints);
add(SubmitButton);
// Declare, set,
and add the "Clear" button.
ClearButton =
new Button("Clear");
PrimaryLayout.setConstraints(ClearButton,
ButtonConstraints);
add(ClearButton);
// Set the constraints
and insert the quit button. This button
// due to the
REMAINDER setting will be the last on the line.
GridBagConstraints
LastButtonConstraints = new GridBagConstraints();
LastButtonConstraints.gridwidth
= GridBagConstraints.REMAINDER;
QuitButton = new
Button("Quit");
PrimaryLayout.setConstraints(QuitButton,
LastButtonConstraints);
add(QuitButton);
// Method that
resets all of the internal values.
resetValues();
}
// The subtotal and total variables.
private double SubTotalOne = 0.0;
private double Total = 0.0;
// The price multipliers for each different
product size.
private double multiplierSmall = 0.5;
private double multiplierMedium = 1.0;
private double multiplierLarge = 1.5;
private double multiplierJumbo = 2.25;
// The local constant base prices.
static double ProdOneBaseValue = 1.0;
static double ProdTwoBaseValue = 1.33;
static double ProdThreeBaseValue = 1.75;
static double ProdFourBaseValue = 8.75;
// Declare all of the variables we'll
use.
private Button SubmitButton;
private Button ClearButton;
private Button QuitButton;
private Checkbox RepeatCustCheckBox;
private Checkbox MailBox;
private Checkbox EmailBox;
private Checkbox PhoneBox;
private List ProductList;
private Choice SizeChoice;
private Scrollbar OrderAmountSlider;
// The labels that will be variable and
change when
// the other selections are changed.
private Label SubTotalLabel = new Label("$0.0
");
private Label TotalLabel = new Label("$0.0
");
private Label AmountLabel = new Label("0
");
private Label PricePerItemLabel = new
Label("$0.0 ");
// The entry field for the user to enter
his name.
private TextField NameEntryField = new
TextField(25);
private TextField ZipEntryField = new
TextField(6);
private TextField StreetEntryField = new
TextField(25);
private TextField CityEntryField = new
TextField(25);
// The comment entry area.
private TextArea CommentTextArea = new
TextArea(4, 25);
// Our own exception . .
private Exception ZeroValueException;
private void updateValues() throws Exception
{
int WhichChoice
= SizeChoice.getSelectedIndex();
int AmountSelected
= OrderAmountSlider.getValue();
int WhichProduct
= ProductList.getSelectedIndex();
double CurrentBasePrice
= 0.0;
double CurrentModifier
= 0.0;
if (AmountSelected ==
0) {
throw(ZeroValueException);
}
switch (WhichProduct)
{
case
0:
CurrentBasePrice
= ProdOneBaseValue;
break;
case
1:
CurrentBasePrice
= ProdTwoBaseValue;
break;
case
2:
CurrentBasePrice
= ProdThreeBaseValue;
break;
case
3:
CurrentBasePrice
= ProdFourBaseValue;
break;
}
switch (WhichChoice)
{
case
3:
CurrentModifier
= multiplierSmall;
break;
case
2:
CurrentModifier
= multiplierMedium;
break;
case
1:
CurrentModifier
= multiplierLarge;
break;
case
0:
CurrentModifier
= multiplierJumbo;
break;
}
AmountLabel.setText(Integer.toString(AmountSelected)+
" ");
double PricePerItem
= (CurrentBasePrice*CurrentModifier);
PricePerItemLabel.setText(Double.toString(PricePerItem)+
" ");
double SubTotal
= (CurrentBasePrice*CurrentModifier*AmountSelected);
SubTotalLabel.setText(Double.toString(SubTotal)+
" ");
TotalLabel.setText(SubTotalLabel.getText());
}
// This method will be called when the
user presses the "Clear" button and
// also when the applet is initialized
in the init() method.
public void resetValues() {
// Reset all of
these labels to zero.
SubTotalLabel.setText("$0.0
");
TotalLabel.setText("$0.0
");
AmountLabel.setText("0
");
PricePerItemLabel.setText("$0.0
");
// Clear all of
the lists and choices.
ProductList.select(0);
SizeChoice.select(0);
OrderAmountSlider.setValue(0);
// Clear all of
the text fields.
NameEntryField.setText("");
StreetEntryField.setText("");
CityEntryField.setText("");
ZipEntryField.setText("");
}
public boolean handleEvent(Event InEvent)
{
if (InEvent.id
== Event.SCROLL_LINE_UP ||
InEvent.id
== Event.SCROLL_LINE_DOWN) {
try
{
updateValues();
} catch
(Exception e) {}
} else
if (InEvent.target
== ProductList) {
try
{
updateValues();
}
catch (Exception e) {}
} else
if (InEvent.target
== ClearButton) {
resetValues();
} else
if (InEvent.target
== QuitButton) {
// Quit the applet.
this.dispose();
} else
if (InEvent.target
== SubmitButton) {
// Submit
the order.
}
return super.handleEvent(InEvent);
}
public boolean action (Event InEvent,
Object SomeObject) {
if (InEvent.target
== SizeChoice) {
try
{
updateValues();
}
catch (Exception e) {}
return true;
}
else
if (InEvent.target
== NameEntryField) {
//
Is the field empty? If so, you could add a
//
pop-up dialog box to alert the user that he
//
has not entered his name.
WDialog.show();
return
true;
}
else
return false;
}
}
class WarningDialog extends Dialog {
private Button OkButton = new Button("OK");
private Label ALabel;
WarningDialog(Frame HostFrame, String
Message) {
super(HostFrame,
"Warning!", false);
ALabel = new Label(Message);
resize(180,100);
setLayout(new
FlowLayout());
add(ALabel);
add(OkButton);
}
public boolean action (Event InEvent,
Object Param) {
if (InEvent.target
== OkButton) {
hide();
}
return true;
}
}
class LogoCanvas extends Canvas {
private Image LogoImage;
LogoCanvas (Image LogoInCanvas) {
// Get the
image and place it in LogoImage. .
LogoImage
= LogoInCanvas;
// Resize
the canvas to fit the Logo exactly.
resize (425, 87);
}
public void paint(Graphics g) {
// Draw the logo
on the canvas.
g.drawImage(LogoImage,0,0,this);
}
}
class HorizBar extends Canvas {
private String LineString;
private int Width;
HorizBar(String InString, int InWidth)
{
// Set the size
of the canvas.
resize(InWidth,
25);
// Set the local
variables equal to parameters so that
// we can use
the values in the paint method.
Width = InWidth;
LineString = InString;
}
public void paint(Graphics g) {
// Set the font
and font metrics class.
Font f = new Font("TimesRoman",
Font.BOLD, 16);
FontMetrics FM
= getFontMetrics(f);
g.setFont(f);
// Draw a line
from x = 0 to x = 15.
g.drawLine(0,
20, 15, 20);
// Draw the string.
g.drawString(LineString,
20, 20);
// Draw the rest
of the line.
g.drawLine(FM.stringWidth(LineString)
+ 25, 20, Width, 20);
}
}
The big problem remaining with the Order Entry System now is getting
the information back to you. All the ways to do this involve opening
a connection back to your server and then transferring the data
in one of many ways. One of these ways involves opening an SMTP
connection and then mailing the information back to you. Another
means is through creating a script on your server to process the
information. And finally, you can write a program that listens
on a specific port waiting for you to make a connection and transfer
the data. The process of constructing these and other network
connections is covered in Chapter 12.
The Order Entry System has been developed to mimic the use of
similar applets in the real world. To make it a good example and
to include as many of Java's features as possible, however, it
is not a completely realistic applet. It did give you a good feel
for what Java can do and how it is done, though.
This chapter covered quite a bit of ground. First, you learned
about the concepts of error and exception handling in Java. Then
you learned about the implementation of these concepts into your
own programs and examined many of the different Java reserved
words such as finally, throws,
try, and catch.
You also learned how to declare your own exceptions and utilize
them and how to use the AppletContext
interface to interact with the browser displaying your applet.
This skill will prove useful in your own applet programming.
You made many changes in the Order Entry System and implemented
them. I also included a listing of the final version of the Order
Entry System. Chapter 11, "Reading
and Writing with Java," will cover the details of inputting
and outputting data with Java.
Next
Previous
Contents
|