Copyright ©1996, Que Corporation. All rights reserved. No part of this book may be used or reproduced in any form or by any means, or stored in a database or retrieval system without prior written permission of the publisher except in the case of brief quotations embodied in critical articles and reviews. Making copies of any part of this book for any purpose other than your own personal use is a violation of United States copyright laws. For information, address Que Corporation, 201 West 103rd Street, Indianapolis, IN 46290 or at support@mcp .com.

Notice: This material is excerpted from Special Edition Using Java, ISBN: 0-7897-0604-0. The electronic version of this material has not been through the final proof reading stage that the book goes through before being published in printed form. Some errors may exist here that are corrected before the book is published. This material is provided "as is" without any warranty of any kind.

Chapter 24 - Managing Applications

by Joseph L. Weber

Java applications are a very powerful way to deliver your Java programs. Before you can use Java applications, however, you have to know how to install them. This chapter discusses how to install and maintain applications. The chapter also provides directions for turning your applets into applications.

In this chapter, you learn to do the following things:

Installing Applications

Java applications come in many forms, but this chapter discusses the two most common: applications that come packaged as a series of .class files, and applications that come as a single .zip file.

Caution

When you install someone else's Java applications, you are giving up the security protection that you are guaranteed with an applet. Giving up this security is not necessarily a bad thing; in fact, you may need to violate it. Just be aware that installing random Java applications can expose you to all the problems that you may encounter with traditional software schemes such as viruses and other malicious software.

Installing Applications from .class Files

Installing an application that comes as a set of .class files is a bit less entangling than installing applications for .zip files. In time, most applications will come with their own installation programs, but for now, you must perform the installation manually.

Create a Directory for the Application

First, you need to designate a directory in which to place your Clock. This directory need not be associated with the directory where you put your Java JDK. Having a deployment plan for your applications is important, however. This plan can be the same one that you use for installing more traditional programs, such as Netscape, or for installing something unique to your Java applications.

** begin caution**
Caution

Keeping backup copies of applications that you value is important. Don't expect applications to become corrupted, but don't ignore that possibility, either.

** end Caution **

Copy the Files

After you create the directory in which you want to place the application, copy all the .class files to it. You should make sure you maintain any directory structure that has already been set up for the application. If you have subdirectories for packages, make sure that you keep the classes in them.

To copy an entire subdirectory on a DOS machine, use the following command:

xcopy c:\original\directory\*.class c:\destination\directory /s

On UNIX machines, the command is:

cp -r /original/directory /destination/directory

If you are deploying an application that you have written, and you are still updating the program, don't make your working copy the same one that you have users accessing. If you happen to be compiling your application at the same time that a user tries to start it, unexpected and undesirable effects may occur.

Make Sure That Everything Works

Now make sure that everything is running the way that it should. Go to the directory in which you placed the Clock application, and type Java Clock. If everything is going as planned, a clock window should appear on-screen as shown in figure 24.1. If not something has gone wrong, make sure you that followed all the procedures correctly. You should also make sure that you have the Java executable in your path. If you have been following through the rest of the book, and you have installed the Java Developer Kit, the Java executable should already be in your path.

Fig. 24.1
The Clock application as it appears under Solaris.

Finishing the Installation

After you copy all the .class files to the correct directory, the next task is to create a script or batch file that you will use to run the application.

You can automate this process so that your users don't always have to type java Clock. Your users will be much happier if they can just type Clock to invoke the Clock program, with out having to also type java,. Making this possible, however, takes you in a different direction, depending on your platform. Ideally, you will be able to follow the same path that you would use for UNIX and Windows 95/NT.(d)Finishing Installing Applications for UNIX_

Finishing Installing Applications for UNIX

In explaining how to install an application under UNIX, this section covers specifically how to do this under Solaris 2.4 using Korn shell. Your implementation may differ slightly, based on your particular operating system and shell.

Create a Wrapper Script

Automating the usage of a Java application under UNIX is done by creating a Wrapper Script. The Wrapper Script is essentially a standard script file that 'wraps' all the commands for a Java Application together. The first task is creating the script. You can create the script with vi, nedit, or your favorite text editor. Listing 24.1 shows an example script for Clock. Note that there are several variables you may need to change for your particular installation.

Listing 24.1 Clock
#Add the applications directory to the CLASSPATH
#set to the directory you have placed the application
#Note, I insert the application directory first to avoid
#having classes from other applications getting called first

CLASSPATH=/ns-home/docs/que/Clock/:$CLASSPATH

#Set the location in which you hold java.
#This directory is probably the same as below
#If you have java in your global path, this line is
#not really necessary

Java_Home=/optl/java/bin/java

#Specify the name of the application.
#Important: Remember this is the name of the class, not the
#file

App=Clock

#Now run the actual program.
#If you have any additional parameters which you need to
#pass to the application, you can add them here.

$Java_Home $App

Test the Script

Copy the text from listing 24.1 to a file called Clock, and make sure that the script is functioning correctly. To test it, simply type the name of the wrapper script, as follows:

Clock &

Fig. 24.2
Type the name of the wrapper script to test the Clock application.

Your application should start and look something like figure 24.2; if it doesn't, make sure that you made the script executable. You can make the script executable by typing the following:

chmod a+x Clock

Don't do this if you don't want everyone to execute your script. If that is the case, check with your system administrator to determine the proper setting to use for chmod.

Copy the Script to a Common Location

It is probably a good idea to place your new wrapper script in the /usr/bin directory so that anyone who has access to the system can run the new script.(d)Finishing Installing an Application for Windows_

Finishing Installing an Application for Windows

This section discusses how to install applications under Windows 95. Aside from a few particulars, the procedures are the same under Windows NT.

You can install an application under Windows in two ways: by creating a batch file, or by using the .pif file.(e)Creating a Wrapper Batch File_

Create a Wrapper Batch File

To install the application with a batch file, use your favorite editor. You can use the Edit command supplied with DOS, Notepad under Windows,or any other text editor. Create a batch file called Clock.bat that contains the lines shown in listing 24.2.

If your application does not use the Windows environment, or if you need to be able to see the output on System.out, use java instead of javaw.

Listing 24.2  Clock.bat
rem add the location where java.exe is located. If it
rem is already in your path don't add this line.
rem change c:\java\bin to the directory you have
rem installed for the JDK - see chapter 3

set PATH=%PATH%;c:\java\bin

rem Set this line to be the directory where your new
rem application is located.

set CLASSPATH = c:\appdir\;%CLASSPATH%

rem Run the actual application, change the applClass to be
rem the correct class for the application you are installing

javaw applClass

Troubleshooting
If your application does not run, and you see an error message similar to Can't find class classname, first make sure that the .zip file is included in your CLASSPATH variable. Next, make sure that the length of the CLASSPATH variable does not exceed the maximum limit, which on Windows machines is 128 characters.

Despite the documentation provided with java.exe at Sun's www.javasoft.com site and that given when you type java, CLASSPATH on Windows machines is not separated by a colon (:). The separation between the elements in the CLASSPATH is accomplished with a semicolon (;). In short, the syntax of CLASSPATH is the same syntax that you use to set your PATH variable.

Wrong syntax:

set CLASSPATH=c:\java\lib\classes.zip:c:\application\

Correct syntax:

CLASSPATH=c:\java\lib\classes.zip;c:\application\

Test the Batch File

To run the application, type Clock at a DOS prompt. The application should start as shown in figure 24.3. Pay special attention to any extra parameters that you have to send to the application. Note that since Clock is a DOS batch file, it is actually case insensitive, so you can run the file as Clock, clock or cLOCK if you would like.

Fig. 24.3
The Clock application running under windows.

Add the Application to Windows

To add this batch file to your Windows environment, switch back to the Windows environment (if necessary), and select the folder in which you want to place the application. Make sure you can actually see the folder's contents, not just the folder icon.

Now create a new shortcut (File, New, Shortcut). Fill in the information for your new batch file (in this case c:\que\Clock.bat), and specify the name under which you want the application to appear on your desktop. The shortcut window should appear as shown in figure 24.4.

Fig. 24.4
The shortcut window appears after you add the Clock batch file.

When you finish creating the shortcut, double-click it. An MS-DOS window appears, and your Clock should start. Now, if you're like most people, having a DOS window pop up in order to start an application is downright annoying. Normally you don't care what is going to System.out, and having a big black obstruction on the screen causes most people just to close the window. Here are a few pointers to make this a bit less obtrusive to you and your users.

To make the MS-DOS window less obtrusive, first, stop the DOS window from appearing on the screen and second, have the DOS window exit on its own as soon as the Java application has started. To make these changes, open the properties for your new application. Right click on the Clock icon. A pop-up menu should appear. Choose Properties from this menu.

The properties window shown in figure 24.5 should appear. Now switch to the Program tab. Change the Run option to Minimized, this will make it so that the DOS Window does not appear. Next, select Close on Exit, which will force the DOS session to exit automatically after the Java application has started. Finally, click OK.

Fig 24.5
In the Properties Window, change the Run option and select Close on Exit

Now, if you double-click the Clock icon, the application starts without the obtrusive DOS window.

Add Applications to Windows Another Way

The other method of adding an application to Windows requires you to know the following:

  1. Where java.exe is located. Alternatively, java.exe must be in the path.
  2. Where the classes.zip file is located
  3. Where your new application is located

First, select the folder in which you want your new application to appear. Then create a new shortcut, as described in the preceding section. When you are prompted to enter the command line option, however, enter the following line as seen in figure 24.6:

c:\java\bin\javaw.exe -classpath c:\java\lib\classes.zip;c:\appDir\ applicationClass

Fig. 24.6
Enter the complete command line in the Create Shortcut window.

You want to replace all the directories and the class name with the ones that apply to your application. If your application does not seem to load, try using java.exe instead of javaw.exe. javaw.exe is an alternative version of Java that returns right away and ignores all the error messages that ordinarily are generated when an application starts. javaw.exe is great for abstracting your users from what is going on, but it makes it difficult to see what is really happening when things don't work correctly.

When you use the -classpath variable, you must be careful to include the classes.zip file in java\lib. Not including this file makes it impossible for any application to start.

Installing Applications from a classes.zip File

With the advent of JDK 2, support was added to deliver Java applications with a single.zip file. This addition makes it easier to deliver an application, because only the zip file and the wrapper are required. In fact, as more and more applications are delivered to market, they undoubtedly will use this method for distribution.

When you install an application from a zip file, be aware of the following things:

The second point here is important. Suppose that you have the applet SkyTune installed in CLASSPATH. SkyToon, which calculates the likelihood that the sky will fall today, has a class called Tune, which deals with the color of the sky. You also have an applet called CDTunes installed; you use this applet to play music CDs in your CD-ROM drive. CDTunes has a class called Tune that handles all the audio input and output from the CD. What happens in this situation where two applications have a class called Tune? When you run CDTunes, the Java interpretor looks down your class path, finds the first instance of the class Tune, finds the class in SkyToons...and chokes.

You can prevent this problem by carefully naming all your classes and/or putting them in packages. If you are running someone else's program, however, there is no guarantee that this problem won't occur. You need to be aware of the possibility in case your applications stop working one day. (You may have this problem when you run applications that come in .class form, too, but the problem is a bit more obvious when it occurs.)

Now you are ready to install an application sent in zip format. Although zip-distributed classes are somewhat trickier to deal with in a management sense than .class distributions, you have to make only one change in your wrapper script or batch file.

If you are using UNIX, refer to the script in listing 24.1, and make the following change:

CLASSPATH="/ns-home/docs/appDir/:$CLASSPATH"

to

CLASSPATH="/ns-home/docs/appDir/application.zip:$CLASSPATH"

If you are using Windows, refer to the batch file in listing 24.2, and make the following change:

set CLASSPATH = c:\appdir\;%CLASSPATH%

to

set CLASSPATH = c:\appdir\application.zip;%CLASSPATH%

These examples assume that the zip file that you received with the application is called application.zip. In reality, the file probably is called classes.zip. The examples simply demonstrate the fact that the file may have any name.(c)Maintaining Multiple Applications on the Same System_

Maintaining Multiple Applications on the Same System

Maintaining multiple Java applications on a single system is not as simple as maintaining several normal programs compiled in binary code, for the following reasons:

You can solve the last two problems yourself. The first problem, however, will have to be resolved by the Virtual Machine vendors.

Consider an example situation. You have been using a Java-based word processor for months. One night, you or your system administrator installs a new version of Java. This new version of Java is 300 times faster (which is the minimum that you can expect from the next generation of VMs), but it has an interesting side effect: it switches the characters a and z. This switch probably is the result of a bug, but what happens to your word processor? Worse, what happens if you don't notice the change for a few days, and you have saved several old documents in the new format? Only one thing can completely prevent such an event: don't upgrade with out making absolutely certain that your new Java machine is 100 percent compatible with previous versions. Developers working before the final Java release went through some growing pains with each new release of the JDK (from JDK pre-beta to JDK 1, and so on. Lest you be scared off from upgrading your VM, most of the problems were very minor, but they almost always required a small code change, and if you don't have the source code, you may not have this luxury.

The second problem deals with the fact that Java is compiled to files that bear the name Something.class. Each class for an applet is contained in its own .class file, and each application can contain dozens of class files.

With each of your Java applications having dozens of classes, it's difficult to avoid using applications that have one or more class bearing the same name as classes from another application. One solution is to place the classes in packages and give each of the packages a unique name. What happens, though, when package names overlap? This situation is not likely to occur if you follow good programming practice, but you may not be able to avoid the problem entirely.

To prevent this class name problem from crashing your applications, you should always place the current application directory or zip file at the begining of the classpath list. In situations where there is code sharing, make sure that the items that you include in the CLASSPATH are correct for the application that you are actually running. If you think that you are pulling the wrong class, strip your CLASSPATH down to nothing and rebuild it with only the required directories. Ultimately, though, you have to put your faith in the programmers. As with upgrading your Virtual Machine, time will tell if good methods will be developed to prevent these situations.

Finally, what do you do about applications that share code with other applications or that load part of their code from the Internet? When you make changes in one application, you must ensure that the changes are backward-compatible. Normally, code that is being deployed is not subject to frequent change, but when you install a new version of an application, you need to make sure that no other programs depend on the code in the old version.

If some programs do depend on code from the old version, maintain the legacy code just in case you need to reinstall the code for other applications. You will look at one minor change of this sort which breaks all applications using the class in the section titled "Pay Attention to Your Constructor" later in this chapter.

In all, the procedure is not quite as simple as installing a new version of Microsoft Word, but it isn't like reinstalling your operating system, either. The key when installing applications is being aware of the downwind effects that every change will cause.(c)Converting an Applet to an Application_

Converting an Applet to an Application

Now that you know how to install and convert an application, you're ready to learn more about Java code. In this section, you convert the applet Clock to the application that you just finished installing.

First though, you need to realize something. Prepare yourself everything the press has told you over the last year is about to be shattered:

Not everyone in the world has realized that the Internet exists. Some people and companies do, but do not yet have access to the Internet, and many companies have access to the Internet but do not allow their users to surf the World Wide Web.

As a result, before long, you probably will want to present your applets to people and companies that are not yet familiar with the Net, or you may want to present your applets to people without forcing them to be connected to the Internet. A perfect example of this is when you want to deliver your applets on a CD-ROM. With Java, there is no reason why the application you deliver on a CD should be any different from what you display on the net. Imagine being able to develop a single application that will run on every platform and that can work over the World Wide Web, Enterprise Network, and CD-ROM.

The key to Java applications (as opposed to applets) is that they do not require a browser to live in. The applications do require a Java VM, but that's less costly to include when sending your applications out than Netscape.

Why should you have your applets function as applications if you can just bundle appletviewer? Applications have four advantages over appletviewer:

In the following sections, you learn how to upgrade an applet to an application. In this example you will convert the applet Clock into the application we installed earlier in this chapter.(d)[Head TK]_

Changing the applet code to an application

The first task is adding a main() method to the application. To do so, open Clock.java in your favorite text editor. Page all the way down until you reach the closing brace (}). Directly before that brace, add the code shown in listing 24.3.

Listing 24.3  new main method for Clock.java
static boolean inApplet =true;
public static void main(String args[]){
 /*set a boolean flag to show if we are in an applet or not */
 inApplet=false;

/*Create a Frame to place our application in. */
 /*You can change the string value to show your desired label*/
 /*for the frame */
 Frame myFrame = new Frame ("Clock as an Application");

 /*Create a clock instance. */
 Clock myApp = new Clock();


 /*Add the current application to the Frame */
 myFrame.add ("Center",myApp);

 /*Resize the Frame to the desired size, and make it visible */
 myFrame.resize(200,200);
 myFrame.show();

 /*Run the methods the browser normally would */
 myApp.init();
 myApp.start();
 }

The following paragraphs explain the changes that you made.

inApplet=false;

First, as you will learn later, you often must do a few things differently when you have an applet that is not actually running in a browser, such as appletviewer or Netscape. As a result, a boolean variable (inApplet) has been added to the class. The declaration for this variable should be placed at the top with the rest of your variables, but it's easier to see it here. Notice that the variable is declared to be static. If you miss this keyword, the compiler growls at you about referencing a nonstatic variable in a static method. main() must be static and public for you to run the method as an application.

Frame myFrame = new Frame ("Clock as an Application");

Next, you create a frame in which to put your new clock. The parameter "Clock as an Application" is placed in the title bar of the Frame. Indicating that the program is being run as an application is good practice; this indication helps eliminate confusion on the part of the user. If you don't want to set the title in the Constructor for some reason, you can create an untitled frame and change the title later, using setTitle(String), if you prefer.

Clock myApp = new Clock();

The next line indicates that you want to create a new instance of the class Clock. A perfectly legitimate question at this point is, why not use this? After all, this is a instantiation of the class Clock already. The primary reason to create a new instance of Clock is to avoid rewriting any of the applet methods to make them static. Just as it is not legitimate to change the variable inApplet if it is nonstatic, it is not legitimate to try to access a nonstatic method. It is, however, ligitimate to access the nonstatic methods of a variable. Bearing that in mind, create a new instance variable of the class Clock called myApp, and add it to the frame.

myFrame.add ("Center",myApp);

The next line adds the new Clock variable to the Frame. This is important, becaue the Clock can't be displayed until you attach it to something.

See "Layout Managers" Chapter 21
myFrame.resize(200,200);
 myFrame.show();

Next, you add the lines myFrame.resize(200,200) and myFrame.show() to the Clock.java file. myFrame.resize(200,200) tells the application to make the frame's size 200 by 200. Normally, when you convert an applet to an application, you know the ideal size for your applet. When in doubt, go ahead and copy the WIDTH and HEIGHT values from your most commonly used HTML file. On those rare occasions when you want the size to be adjustable, use the techniques covered in defaulting, where you learn how to account for parameter data, to read in the size from the command line.

When the applet has been added to the frame, technically, you could go through the normal applet methods init() and start() right there. Contrary to popular belief, however, this procedure is not a good idea. If your applet uses double buffering or requires any other image that is built with the createImage(x,y) method, the procedure will not work until the frame has been shown(). The drawback is that you will see a flicker as the frame comes up with nothing in it. Keep this fact in the back of your mind even if you're not using createImage(x,y) now, because this minor fact is not documented anywhere and has caused this author hours of headaches.

 myApp.init();
 myApp.start();

Finally, you add the lines myApp.init() and myApp.start() to your function. Because your application is not running in the browser, the init() and start() methods are not called automatically, as they would be if the program were running as an applet. As a result, you must simulate the effect by calling the methods explicitly. It should be pointed out that if your application does not appear, you may want to add the line myApp.repaint() to the end of the main() method.

import java.awt.Frame

Before you save your new copy of Clock.java, you need to make one more change. Go to the top of the file in which you are performing your imports, and make sure that you are importing java.awt.Frame. Then go ahead and save the file.(d)[Head TK]_

Compiling the application

The next step is recompiling the application. Recompiling an application is no different from compiling an applet. In this case, type the following:

javac Clock.java(d)[Head TK]_

Testing the application

Now you can test your application. To do so, you need to invoke the Java Virtual Machine, followed by the class name, as follows:

java Clock

The application should now appear as shown in figure 24.7.

Be sure to maintain proper capitalization at all times.

Fig. 24.7
The Clock running as an Application

Accounting for other applet peculiarities

The most difficult problem to deal with when you convert applets to applications has to do with duplicating the effect of a parameter tag and other applet-specific tasks. You can handle this situation in many ways; the following sections discuss two of the most common solutions.

Defaulting

The first solution is defaulting. In defaulting, the idea is to provide the application with all the information that it would be getting anyway from the HTML file. In a sense, this solution is exactly what you did when you told the frame what size you wanted to use with resize(x,y). To do this for the <param> items requires rewriting the getParameter method.

Clock has several parameters that it receives in <param> tags. If you have run the Clock up to this point, you no doubt have noticed that the current Clock displays a bit differently from the one that you originally saw in Netscape. This is because the parameters that normally come from the Clock.html file are not present. Take a look at the number of <param> tags in listing 24.2

Listing 24.4  Clock.html
<TITLE>Clock 2.0</TITLE>
<H1>Clock 2.0</H1>
<HR ALIGN=CENTER WIDTH=75%>
<applet code="Clock.class" width=200 height=200>
<param name=num_lines value=3>
<param name=hour_len value=60>
<param name=minute_len value=75>
<param name=second_len value=95>
<param name=hour_col value=ff0000 >
<param name=minute_col value=00ff00>
<param name=second_col value=0000ff>
<param name=border_col value=00ffff>
<param name=background_col value=cccc22>
<param name=timezone value=1>
</applet>

To mimic these effects in your new application, add the method shown in listing 24.5 to your current Clock.java file.

Listing 24.5 getParameter() method for Clock.java
public String getParameter (String name){
 String ST;
 if (inApplet)
 return super.getParameter(name);
 //If we are not in an applet we default all of the values.
 if (name == "num_lines")
 return "3";
 if (name == "hour_len")
 return "60";
 if (name == "minute_len")
 return "75";
 if (name == "second_len")
 return "95";
 if (name == "hour_col")
 return "ff0000" ;
 if (name == "minute_col")
 return "00ff00";
 if (name == "second_col")
 return "0000ff";
 if (name == "border_col")
 return "00ffff";
 if (name == "background_col")
 return "cccc22";
 if (name == "timezone")
 return "1";
 return null;
}

If you are going to have several parameters, you should use a switch statement. A switch, however, requires an integer, which you can get by using the hashCode() of the String. Since multiple Strings can have the same hashCode() you must then make sure you really have the correct String. This makes the solution much more involved. Nonetheless, if you are working with several <param> tags, consider using this alternative method.

This method replaces the duties that are normally performed by the java.applet.Applet class with your own default values. Notice that the first thing you do is check to see whether you are in an applet (if (inApplet)). If so, you use the getParameter(String) method from your super class (java.applet.Applet). Doing this maintains your normal pattern of operation when you go back and use Clock as an applet again. The idea is to have one program that can run as both an application and an applet, as shown in figure 24.8.

A better way to handle the getParameter is to implement appletStub, but without a complete explanation of interfaces, such an explanation would be purely academic. If you plan to implement several aspects of java.applet.Applet, refer to chapter 12 for more information.

Fig. 24.8
Running the Clock applet. 

Second Way to Add <param> Information

Defaulting is a quick and easy way to get into an application the extraneous information that you normally leave in an HTML file. Odds are, however, that if you took the time to include a parameter tag in the first place, you don't want the values to be fixed. After all, you could have hard-coded the values to start with, and then you wouldn't have this problem in the first place. How do you get information into your application from the outside world? The easiest answer is to get it from the command line.

As you recall, the main method takes an array of Strings as an argument. You can use this array to deliver information to an application at run-time. This section addresses one of the simplest cases: sending the WIDTH and HEIGHT information to the application from the command line. While, the section doesn't also explain how to insert the information for a <param>; you should be able to deduce from this example how to do it for <param> tags on your own.

To use the information from the command line, you need to make a few modifications in the main() method. Listing 24.6 shows the new version.

Listing 24.6 new main method
public static void main(String args[]){
 /*set a boolean flag to show if we are in an applet or not */
 inApplet=false;

 /*Create a clock instance. */
 Clock myApp = new Clock();

 /*Create a Frame to place our application in. */
 /*You can change the string value to show your desired label*/
 /*for the frame */
 Frame myFrame = new Frame ("Clock as an Applet");

 /*Add the current application to the Frame */
 myFrame.add ("Center",myApp);

 /*Resize the Frame to the desired size, and make it visible */
 if (argv.length>=2)
 /*resize the Frame based on command line inputs */
 myFrame.resize(Integer.parseInt(args[0]),Integer.parseInt(args[1]));
 else
 myFrame.resize(200,200);
 myFrame.show();

 /*Run the methods the browser normally would */
 myApp.init();
 myApp.start();
}

Make the necessary changes, and recompile the program. Now you can run the Clock at any size you want. Try the following:

java Clock 100 100

At first glance, your new main method is almost identical to the one in listing 24.3. The main difference is a group of six lines:

/*Resize the Frame to the desired size, and make it visible */
 if (argv.length>=2)
 /*resize the Frame based on command line inputs */
 myFrame.resize(Integer.parseInt(args[0]),Integer.parseInt(args[1]));
 else
 myFrame.resize(200,200);

The first line of actual code checks to see whether the user put enough information in the command line. This check prevents null pointer exceptions caused by accessing information that isn't really there. Besides, you probably want the user to be able to run Clock at its normal size without specifying the actual size.

The next line is the one that does most of the work. It should be fairly obvious to you what is happening in this code, but you should know why you need to use Integer.parseInt on the array values. At runtime, the Java machine isn't aware of what is coming in from the command line; it simply sees a string. To convert a String to an int, you need to use the class Integer's parseInt(String) method.

To be complete, the parseInt method should be surrounded by a try{} catch{} block, in case something other than an integer is typed in the command line.

Making the Window Close Work

By now, you probably have noticed that to close your new Clock application, you have to press Ctrl+C or in some other way cause the operating system to close your application. This section reveals to you the secret method by which all MagnaStar, Inc., applications and applets close their frames by a normal method.

The answer is to not use the frame from java.awt.Frame. This frame ignores the Event.WINDOW_DESTROY event and doesn't bother to pass it along to its container objects. To get around this situation, use the goodFrame class shown in listing 24.7.

Listing 24.7goodFrame.java
/* ----------------------------------------------------------------
 * goodFrame , Copyright (c) 1995 MagnaStar Inc, All Rights Reserved.
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for NON-COMMERCIAL purposes and without fee is hereby
 * granted, provided that this copyright notice and appropriate documentation
 * appears in all software that contains this code, or is derived from it.
 *
 * MagnaStar Inc. MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
 * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
 * LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. MagnaStar Inc. SHALL NOT BE LIABLE
 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 *
 * You may reach MagnaStar Inc. at info@magnastar.com
 * P.O. Box 70, Waupun, WI 53963
 *
 * For more information see:
 * http://www.magnastar.com */

import java.awt.Event;
import java.awt.Component;
/** GoodFrame extends java.awt.Frame and acknowledges standard window
 * Close and minimize commands */

public class goodFrame extends java.awt.Frame{

//Constructors duplicate those from java.awt.Frame
public goodFrame (){
 super();
}

public goodFrame(String title){
 super(title);
}

public boolean handleEvent(Event evt){
 //Acknowledge minimize requests
 if (evt.id== Event.WINDOW_ICONIFY){
 hide();
 return false;
 }
 //Acknowledge window close requests
 if (evt.id == Event.WINDOW_DESTROY){
 //Pass the destroy event along to the components.
 //This should be used to stop all Threads
 Component c[] = getComponents();
 for (int x=0;x<c.length;x++)
 c[x].handleEvent(evt);
 //Destroy the current Frame
 dispose();
 return false;
 }
 //Default to the normal handleEvent
 return super.handleEvent(evt);
}

}

To implement this class, copy goodFrame.java to the directory in which the Clock.java class is located. Next, edit Clock.java. Replace all the instances of Frame with goodFrame, and make one more change: rather than import java.awt.Frame at the top of the program, import goodFrame. Now recompile the program. Everything should work exactly as it did before, with one change: if you click the close icon, the application disappears.

Now you need to make one more change to Clock to get it to quit completely. Add the following method to your Clock applet:

public boolean handleEvent(Event evt){
 if (evt.id == Event.WINDOW_DESTROY){
 if(inApplet){
 stop();
 destroy();
 return true;
 }
 else {
 System.exit(0);
 }
 }
 return super.handleEvent(evt);
}

This method causes Clock to run through the standard exit procedures under an applet (if (inApplet)). The real key, however, is that when you run it as an application, Clock calls System.exit(0). Before you do one more recompilation of Clock.java, add one more line to the top of Clock.java to import the Event class:

import java.awt.Event;

Now, recompile and run Clock one last time. If you click the window close icon, Clock now exits like a normal program.(d)Checking All the Applet Methods_

Checking All the Applet Methods

When you convert your own applets to applications, you need to perform one last step. You need to search for all methods in java.applet.Applet that are valid only with respect to a browser. Most commonly, you need to search for the methods described in the following sections.

getAppletContext()

Fortunately, most of the things that you will do with getAppletContext(), you can ignore with applications. showDocument(), for example, has no meaning without a browser. Attempting to execute getAppletContext().showDocument() produces an error on System.out, but the application shouldn't crash because of it.

Similarly, showStatus() usually is not relevant with applications. In applets that use the applet context to display information, the easiest thing to do usually is to surround the specific code with an if (inApplet){} block, and ignore it if you're not in an applet.

What do you do if you really have to see that information? You can select the top and bottom 20 lines of the frame and write into the paint method a section that displays the applet-context information there. Why do you select the top and the bottom? Due to a strange quirk between the UNIX version of Frame peer and the Windows 95 version of Frame peer, each system chops out a 20-line area in which it can display its "warning applet" message. On Windows machines, this area is the top 20 lines; on UNIX machines, it is the bottom 20 lines.

If you're not convinced, go to the following URL:

http://www.magnastar.com/ultra_nav

If you are on a Windows machine, you should see an information bar at the top of the frame. If you're on a UNIX machine, that bar is at the bottom. The bar is being drawn at both the top and the bottom; you are just seeing only one.

getCodeBase() and getDocumentBase()

getCodeBase() and getDocumentBase() are a bit trickier to deal with. Both of these methods return a URL, and you don't want to limit yourself to having the user connected to the Internet. After all, if the user can access your Web site, you probably have him or her downloading the applet directly from you, so you would have no need to turn the applet into an application.

You usually dealing with getCodeBase() and getDocumentBase() on a case-by-case basis. If you can get away without the information, ignore it. If you really need the information from getCodeBase() or getDocumentBase(), you may have to give it a hard-coded URL or one that you read from the command line.(e)Pay Attention to Your Constructor_

Paying attention to your constructor

Frequently, when converting applets you will find yourself creating a constructor for your class other than the null constructor. Creating a custom constructor is a perfectly desirable thing to do to pass information from the command line or other information. If you do this, however, make sure that you add the null constructor back in manually (the null constructor is the constructor which does not take any paramenters on input). If you create another constructor, Java doesn't automatically generate a null one for you. You won't even notice that you need one until you are working on a project and another class needs to create an instance of your applet, for a thread or something. When this situation occurs, the class attempts to access the null constructor. Now, even though you didn't actually delete the null constructor from the class, it is no longer there. The error message that you get will look something like this:

java.lang.NoSuchMethodError
 at sun.applet.AppletPanel.run(AppletPanel.java:200)
 at java.lang.Thread(Thread.java)

Notice that nothing in the error message tells you anything about your classes. The error doesn't even look like one that involves your class; it looks like a bug in AppletPanel. If you encounter this situation, the first thing to do is delete *.class and recompile the whole program. Then the compiler will be able to catch the missing Constructor call.

createImage

If you are using createImage, and the Image variable is being returned as null when you covert your applet to an application, make sure that you have made the frame visible first. See the caution under "Converting the applet code to an application" in the section titled "Changing the applet code to an application" for more information.

Packaging your applications in ZIP format

Now that you have converted your applets to applications, you can send them to your clients. The best way to deliver the applications is in a single zip file.

When you package your own applications in zip format, make sure that you don't use compression. Due to the way that the Java interpreter uses the zip files, the files can only be stored in the zip file-not compressed.

Be aware that you cannot deliver applets in the .zip format. Sun and Netscape may see the wisdom of this in the future, but at least in JDK version 1.0, you cannot package applets in zip format.

Under Windows

Currently, PKZIP, the most popular zip program, does not have support for long file names, so you have to use an alternative zip compression program. When PKZIP does support long file names, however, the command should be:

pkzip -e0 classes.zip *.class(d)Under UNIX_

Under UNIX

On UNIX machines, you can use Zip. Zip 2.0.1, from Info-ZIP, is available at a variety of FTP sites. The URL for the Web site is http://quest.jpl.nasa.gov/Info-Zip/Info-Zip.html. The command for Info-Zip to zip .class files is:

zip -0 classes.zip *.class

When you deliver applications, be sure to include directions for your users on how to get the JDK (if you are not including it with your application). In general, it is also a good idea to include both a batch file and a script file to allow both UNIX and Windows users to access your applications.

QUE Home Page

For technical support for our books and software contact support@mcp.com

Copyright ©1996, Que Corporation