|
Articles Index
By Tony Squier
July 1998
Have you ever asked, "What is the difference between an applet and an
application?" Or, "How do you turn an applet into a standalone application?"
If so, then you are by no means alone; these questions are often asked, and the
intention of this article is to help dispel the confusion behind these questions.
If you want to turn an applet into a standalone application, it helps to understand
that there are two main differences between an applet and a full-blown application,
and these differences are:
-
The Java language's applet class provides two major functions: a
panel to contain other user interface components, and a set of APIs for
accessing various resources. In a standalone application, you typically
have a top-level Frame in which your main user-interface components reside;
but with an applet, the top-level Frame is the browser.
-
Applets typically use a fairly restrictive security policy as
implemented by the browser's Java
Virtual Machine1 (JVM) Security Manager.
In a standalone application, however, the security policy is usually more
relaxed. This difference can get you into trouble when you attempt to create
an applet from an existing application. If your application
writes to the file system, for example, the applet's security policy will likely
disallow this operation. This kind of security policy difference can many
times break an application that is run as an applet. For a detailed
explanation of applet security policies, see
Frequently Asked Questions - Java Security.
But, when running an applet as a standalone application, the Security
Manager usually doesn't present as many obstacles.
So how do you go about converting an applet into a standalone application?
For example, say you've written a nifty applet and you want users within
your organization to be able to run it from outside a browser. The process
is fairly simple.
You have two choices for making your applet run standalone: one is a
design change and the other is a configuration change.
Redesigning or Rearchitecting?
Typically, an applet can avoid having too much of the program's logic and
user interface components within your extended applet class. If you've
written your program in such a way that the applet class is used as a
wrapper for another class that does most of the work, then it's fairly easy
to run the program standalone. Just create your own 'standalone
wrapper'.
For example, in the following applet, the logic and user interface
components are part of the applet.
public class MyApplet extends Applet {
private Button _myButton;
public void init() {
_myButton = new Button (getParameter (
"label"));
_myButton.addActionListener (
new AbstractAction () {
public void actionPerformed (
ActionEvent event) {
Frame f = new Frame("Frame");
f.pack();
f.show();
}
}
);
add (_myButton);
}
}
|
If you remove the logic and components from the applet and put them into
some other class, you've got a program that is much easier to run standalone.
public class MyA
public class MyUI extends Panel {
private Button _myButton;
public MyUI (String label) {
_myButton = new Button (label);
_myButton.addActionListener (
new AbstractAction () {
public void actionPerformed (
ActionEvent event) {
Frame f =
new Frame("Frame");
f.pack();
f.show();
}
}
);
add (_myButton);
}
}
|
To make the program into an applet, just provide an applet wrapper as shown
below:
public class MyApplet extends Applet {
private MyUI _ui;
public void init() {
_ui = new MyUI ("Push Me");
add (_ui);
}
}
|
To make the program run standalone, you simply create a different wrapper,
as in the following example:
public class MyApplication extends Frame {
private MyUI _ui;
private MyApplication(String label) {
_ui = new MyUI (label);
add ("Center", _ui);
}
static public void main (String argv[]) {
MyApplication a = new MyApplication (
"Push Me");
a.pack();
a.show();
}
}
|
This technique is great to use especially if you're just starting your
project and haven't created an applet yet. In some cases you can easily
modify your existing applet as shown above, but sometimes this can
cause too much work, in which case you might consider using AppletStub, described
in the next section.
Making a Configuration Change with AppletStub
If rearchitecting isn't your idea of fun, another way to run your applet
standalone, without changing any existing code, is to create an AppletStub!
The AppletStub class is created
for you by the browser each time an applet is loaded. The AppletStub
contains most of the information you need when the applet is loaded and
started by the browser.
A simple standalone implementation of the AppletStub needs to do the
following:
- Parse parameters from the command line
- Return correct values for getCodeBase() and getDocumentBase()
- Provide implemetation for other required methods
Once you've created your AppletStub implementation, you can hook it to your
applet by providing a static main method in your applet's list of methods.
Here is a sample AppletStub implementation called MyAppletStub:
public class MyAppletStub implements AppletStub {
private Hashtable _properties;
private Applet _applet;
/**
* Creates a new MyAppletStub instance and initializes
* thei nit parameters from the command line.
* Arguments are passed in as name=value pairs.
* Reading the command line arguments can be made more
* sophisciated depending on your needs, but the basic
* idea will likely remain the same.
* Also, this particular implementation doesn't deal
* very well with invalid name=value pairs.
*
* @param argv[] Command line arguments passed to Main
* @param an Applet instance.
*/
public MyAppletStub (String argv[
], Applet a) {
_applet = a;
_properties = new Hashtable();
for ( int i = 0; i *lt; argv.length; i++ ) {
try {
StringTokenizer parser =
new StringTokenizer (
argv[i], "=");
String name = parser.nextToken(
).toString();
String value = parser.nextToken(
"\"").toString();
value = value.substring(1);
_properties.put (name, value);
} catch (NoSuchElementException e) {
e.printStackTrace();
}
}
}
/**
* Calls the applet's resize
* @param width
* @param height
* @return void
*/
public void appletResize (
int width, int height) {
_applet.resize (width, height);
}
/**
* Returns the applet's context, which is
* null in this case. This is an area where more
* creative programming
* work can be done to try and provide a context
* @return AppletContext Always null
*/
public AppletContext getAppletContext () {
return null;
}
/**
* Returns the CodeBase. If a host parameter
* isn't provided
* in the command line arguments, the URL is based
* on InetAddress.getLocalHost().
* The protocol is "file:"
* @return URL
*/
public java.net.URL getCodeBase() {
String host;
if ( (host=getParameter (
"host")) == null ) {
try {
host = InetAddress.getLocalHost(
).getHostName();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
java.net.URL u = null;
try {
u = new java.net.URL (
"file://"+host);
} catch (Exception e) { }
return u;
}
/**
* Returns getCodeBase
* @return URL
*/
public java.net.URL getDocumentBase() {
return getCodeBase();
}
/**
* Returns the corresponding command line value
* @return String
*/
public String getParameter (
String p) {
return (String)_properties.get (p);
}
/**
* Applet is always true
* @return boolean True
*/
public boolean isActive () {
return true;
}
}
|
To use this stub, add a main method to your applet. For the example
given above, the new MyApplet will be as follows:
public class MyApplet extends Applet {
private Button _myButton;
public void init() {
_myButton = new Button (getParameter (
"label"));
_myButton.addActionListener (
new AbstractAction () {
public void actionPerformed (
ActionEvent event) {
Frame f = new Frame(
"Frame");
f.pack();
f.show();
}
}
);
add (_myButton);
}
static public void main (String argv[]) {
final Applet applet = new MyApplet();
System.runFinalizersOnExit(true);
Frame frame = new Frame (
"MyApplet");
frame.addWindowListener (
new WindowAdapter()
{
public void windowClosing (
WindowEvent event)
{
applet.stop();
applet.destroy();
System.exit(0);
}
});
frame.add (
"Center", applet);
applet.setStub (new MyAppletStub (
argv, applet));
frame.show();
applet.init();
applet.start();
frame.pack();
}
}
|
The AppletStub technique is easier to do than rearchitecting, but may still
not work completely if your applet depends on the AppletContext for
anything. However, in many cases, this technique is an easy way to make
your applets run standalone.
Tony Squier is a JDC tools engineer. He developed the JDC
registration-management code. He invites any feedback you have about
the article or the code, such as enhancements or potential bugs. If you
have comments please send them to:
Tony Squier
_______
1 As used on this web site, the terms
"Java virtual machine" or "JVM" mean a virtual machine for the Java platform.
|
|