a partial Java application program designed to run inside the womb of a web
browser, with help from some predefined support classes.
Applet Difficulties
java.applet.Applets must
run inside a web browser (or AppletViewer). You can also run them in Java Web
Start to avoid the peculiarities of individual browsers. You cannot run them
from the java.exe command line. To spawn a web browser from within an
application to get it to display an Applet, see the
tips under HTML rendering. Applets
are typically automatically downloaded over the web freshly every time they are
executed. They can also be run from local hard disk. In contrast, applications
cannot be run inside a browser, though it is possible to make a dual mode
program that can run either as an Applet or
application. Applets run on the client’s
machine. In contrast, Servlets run on the host
webserver.
Applets are harder to write than applications. I
would recommend that beginners start with applications. With Applets
you have the following complications:
- Your entire logic must fit in the straight jacket of four methods init,
start, stop and destroy.
- Unsigned (ordinary) Applets are restricted in
hundreds of not-well-documented ways. They are not even allowed to read files.
- An Applet must run inside a browser. This adds an
extra level of complication and uncertainty as different browsers have different
bugs.
- Unless you spin off a separate Thread, an Applet has
no mechanism to do any calculation that takes more than a fraction of a second.
The big appeal of Applets to the beginner is that
you can post your handiwork on the web for everyone to play with and admire.
Unsigned Applet Restrictions
To make Applets very safe to run, even when they
were composed by teens with the morals or skill of Beavis and Butthead, Applets
are severely restricted. Unsigned Applets (without
special permission to bypass security) are not permitted to:
- talk to any server but the one you were loaded from. No talking to strangers. If
they were loaded from a local disk, they can’t talk to any
webserver at all. They can’t load classes, read files, or have socket
communications with any webserver but mom, the server htey were loaded from. Applets
can send/receive email to/from a different host, but only via the home host.
- I have discovered by experiment that when an Applet
runs locally, it is only allowed to read files in the same directory or in a
subdirectory of that directory. It can’t read files in the parents or
sibling directories, just child/grandchild directories. Oddly, it does not
matter where the jar itself is, but where the web page is that has the <applet
tag. The files the Applet reads have to be “downstream”
of that page. You will notice multiple snippet
subdirectories all over my website. This is because Applets
could not get at a central snippet directory. The
place where I put the code snippets for a given webpage has to be in a branch
off the directory containing the web page. My only other alternative would be to
always put the code snippets in the same directory as the web page. I am not
sure if the same restriction applies to Applets run
on a webserver.
- I have not experimented with https:. Please let me know
if you can use https in an unsigned Applet
and if you can mix http: to fetch the Applet
jar and http: to fetch the data.
- I have discovered by experiment that when an Applet
runs from a website, it is only allowed to read files in the same directory as
the web page or in a subdirectory of that directory, (downstream
from the webpage). It can’t read files in the parents or sibling
directories, just child/grandchild directories. It does not matter where the jar
is, just the web page and the files that you try to read. This means unsigned Applets
usually end up bundling everything they need to read as resources in the jar.
- read or write local files on the client machine. They are not even
allowed to look in a directory or test for the existence of a file. You can
however read a file (resource) embedded in the jar
with Class.getResource or Class.getResourceAsStream.
It can also read from the server via a URL. Even when
your Applet is loaded from hard disk, it still may
not do file I/O even via file: URLs.
- Use System.setOut or System.
setErr to redirect the console.
- Look at the restricted system properties, or get an enumeration of all the
system properties. See Wassup.
Don't use Color.getColor
which interrogates the system properties.
- Monitor mouse motion.
- Print in JDK 1.1, though you can in JDK 1,2+. The user has to ok the printing
though.
- Send email to a server other than the one it was loaded from.
- Talk to a serial port.
- Talk to a parallel port.
- Change thread priority, even lower it.
- Read or write the clipboard. However, users can manually cut/paste your AWT
components without security clearance. The restriction is on programmatic
control of the clipboard. Swing components have no cut/paste ability at all.
- Install software.
- Execute any native code. If you use native JNI code, things get really
complicated vis a vis security and signed Applets
with native code. You are better off to use Java Web Start.
- Exec external programs.
- Issue an RMI call to a remote object running on a different server than the Applet’s.
- Determine the structure of an object (fields, methods, values, etc.) using the
Reflection API.
- Use the Preferences API to store or look at configuration information in the
registry.
If your Applet needs to do
any of the above things, it must be signed.
Now that IE has dropped Java, it is reasonable to ask your clients to upgrade to
the latest Java, understanding that some will not. For them, you must develop or
at least test on earlier versions. Don’t just assume that just because you
did not use any new features that you are home free.
Standalone Java applications are not so limited. Exactly what the limitations
are is controlled by the security manager in the browser. If the user installs
an alternate security class, the Applet may have
more powers. The security restrictions are controlled entirely by the browser.
There is nothing to stop you from writing a non-conforming browser that has
quite different security restrictions for Applets.
However, in practice, you write code to sign your jars and bypass each of the
five different security schemes used in browsers.
Programmers bitterly complain about these restrictions. The restrictions protect
the end user from malicious web Applets they might
encounter on the web. Without such protection, vicious Applets
could destroy the user’s hard disk, print reams of paper, phone out on a
spare serial port and rack up long distance bills, go sniffing on the LAN for
the company books… You don’t want to give those powers to psychotic
strangers — those same people who stay up late at night writing viruses.
Applet Gotchas
- Don’t try to make Applets
work on your website with naked class files. Always bundle everything, classes,
gifs, configuration scripts etc. up into a jar. This bypasses many classpath
headaches, and it downloads faster. Further, the chances are much better your Applet
will work first time on the website once you get it working locally out of a jar.
- Applets are a pain in the behind. If you possibly
can, use Java Web Start instead.
- Don’t try to use any of the Applet methods in
your constructor such as getCodeBase. They depend
on a private field called appletStub that does not get
initialised until just before your init method is
called. You will get NullPointerExceptions if you
fail to heed this advice.
- Unsigned Applets are extremely restricted in what
they can do. Carefully review the list above. In
particular, Applets cannot write to the local hard
disk or talk to a server other than the one they were loaded from.
- AppletContext.getApplets
will get all the Applets on the page, not just other
instances of the current class. Further, sometimes this
instance is included, sometimes it is not. Don't count on it working either way.
HTML to Invoke an Applet
I find it wise to sandwich the <applet…>…
</applet> tags in <p> tags like
this:
that stray-looking > is not a mistake. It has to be
there to close the opening <applet tag This way
the Applet has lots of room to display. If you leave
them, out your Applet may be rendered off the right
edge of the screen, where you probably won’t see it.
I repeat. Always bundle your
Applet (or
JApplet)
classes and resources into a jar!
- You can then invoke your Applet from any page.
- The classes download faster.
- It is clear exactly which classes your Applet may
use and not use.
- There are no classpath mysteries.
- It is always clear which version of the class files you are using.
- Everything just works more smoothly.
Here is tip to find the optimal size parameters. Run the Applet
as an application. Drag the frame to the optimum size. Use Paint
Shop Pro to capture a screen snapshot of the frame, excluding the
menu bar. Then look in the lower right corner of the PSP window to discover the
size for the <applet height and width
tags. Then measure including the menu bar to discover the size for the Frame.setSize(
width, height ) when running as an application. It will need about 24
pixels extra height. This trick saves a lot of guesswork and experimentation to
home in on the optimal values.
When debugging Applets, remember to click
Shift-Reload in your browser, not just plain Reload
to attempt re-running with your new version. Shift-Reload supposedly flushes the
cache of class files. This usually does not work. You have to exit the browser
and restart. It is a good idea to put something unique in every incarnation of
your code so you can tell if you are running the old or new code. I do it by
flipping a background colour or setting a micro version number.
You can go crazy debugging Applets because the
browser sometimes caches old copies of jars, classes, html… It is best to
start each test with at least a fresh loading of your browser, preferably with
all its caches deleted using a bat file before each test. I often start
different a different browser for each test to get a clean start, e.g. Opera,
Firefox, SeaMonkey, Netscape, IE.
It is best to debug as an application, then at the last minute convert to an Applet.
Applet Tags
Applets are invoked to run in browsers by the <applet…>
tag. Applets won’t work if you load them
directly with your browser as if they were web pages! The HTML commands for
firing up an Applet are exceedingly picky. It
matters whether you have .class or not. I suggest you
look at the files that come with the Conversion Amanuensis to see how to run an Applet/Application
with/without jars, locally, on a web site, with various browsers and run times.
Here is the basic structure:
| HTML Tag |
Comments |
| <applet |
| code= "MyClass.class" |
The name of the class file for the Applet. Make
sure the case and name exactly match the name of the *.java file, *.class file,
and class name. For a class in a package this would have dots in it, e.g. com.mindprod.mypackage.Myclass.class
, but it would not have any directory qualification. You are not allowed to
specify an absolute URL or absolute fully qualified hard disk filename. Strange
as it sounds, you must specify the trailing .class,
though some browsers let you get away without it. All the Sun tutorials do it
with the .class. If you leave it out, you will just
get a gray square with no error message, even if you have manifest Main-Class
entry. |
| width= "330" |
width of entire Applet display in pixels. There
is nothing the Applet can do itself to change this.
If you needed variable size you would have to resort to JavaScript or a server-side
technology to generate HTML pages with the appropriate size. This can be
specified as a percentage e.g. width="100%"
or with CSS commands. Then the Applet will grow and shrink with the enclosing
window. |
| height= "240" |
height of entire Applet display in pixels. There
is nothing the Applet can do itself to change this. |
| archive= "Everything.jar,Sub/MoreStuff.zip" |
Resource file, classes etc. Your ARCHIVE parameter
must have a list of the absolute or relative jar files, separated by commas (no
spaces). (Watch out! The ARCHIVE tag in <OBJECT
is space-separated!) If you have too little or too much qualification, or if you
fail to use the file naming conventions of your server, you will be in trouble.
You are probably best to use absolute URLs or fully qualified hard disk file
names. Whether the archive is supposed to be relative to the current HTML
directory, the CODEBASE, or all elements of the
classpath is unclear. The forms of archive I use most are archive="myapp.jar"
archive="../myapp.jar" and archive="somedir/myapp.jar". |
| codebase= "http://mydomain.com/" |
I suspect CODEBASE is simply broken in the current implementations.
Theoretically it is the absolute or relative URL/directory where class files are,
like a one-element classpath. Normally the class files are in the same directory
as the html, so you don’t need it. In practice, I have found your CODEBASE
parameter must have an absolute http:// -style
reference to the base directory where the code is stored. The codebase is only
needed when your code resides somewhere other than where the html page was
loaded from. For a local hard disk, the only thing I could get to work on NT
with all browsers and Appletviewers is leaving the CODEBASE out entirely which
causes the CODEBASE to default to the same directory as where the enclosing HTML
page was loaded from. You may find for your platform you have to code it
something like this: file:///C|//MyDir/ or C:\MyDir\.
I also further suspect that some browsers will take the a relative CODEBASE as
relative to each element of the CLASSPATH, not relative to the current HTML
directory. If the user of the signed Applet is
behind a firewall, for some strange reason, if he invokes the Applet
using the IP rather than the DNS name of the website in the codebase e.g CODEBASE=
"http://65.110.21.43/"
instead of CODEBASE= "mindprod.com"
, all works. Otherwise you get a trustProxy Property
error message. |
| vspace= "10" |
pixel width of border above and below the Applet |
| hspace= "10" |
pixel width of border left and right of the Applet |
| align= "left" |
how this Applet aligns, treated like a image |
| alt= "You need Java to run this
Applet" |
what to display if no Java interpreter available. Normally this would be the
same text that appears just before the </applet>
tag. This optional attribute specifies any text that should be displayed if the
browser understands the APPLET tag but can’t run Java Applets. |
| name= "receiver" |
Name for this Applet so that other Applets
can communicate with it. Other Applets would do a
Applet Applet.getAppletContext().
getApplet( "receiver"
) to get a handle on this Applet. You don’t
need this parameter if you use Applet Enumeration Applet.
getAppletContext(). getApplets()
which gets you a list of all the Applets running on
the page (including yourself). |
| mayscript |
Lets Applet read/write cookies and peek at the
page it is embedded in using JavaScript DOM. |
| > |
All that stuff above has to be inside the <applet…
>, but the params may not be. |
| <param name= "favouriteColour"
value= "orange" > |
The param statements are Java’s ode to
verbosity. They pass information to the Applet.
There can be as many param statements as you like. Beware of params with decimal
points. <param name= "cost"
value="10.00" > When your Applet
runs in Europe, it may be expecting a comma instead unless you take special
precautions.
Param values cannot contain embedded " or
newline characters. You can encode the parameters using HTML entities such as ",
> or &#nn;.
The browser should automatically convert them for you to the equivalent
character when you do your getParam. If the browser
does not convert them for you, you can convert the entities back to characters
with my free entities package. I tested
recent versions of Opera, Netscape, Firefox, Mozilla and IE and they call
converted entities to characters automatically. Unfortunately, there is no &
entity for \n.
and 
 do not work. You will have to roll
your own convention, perhaps using the character pair \n
or some rarely used character such as ~ or `
to stand in for newline. You can’t use <br>
because < and >
are awkward characters in their own right. Awkward
characters are defined as ones that have be specially escaped/quoted/represented
to use them literally because they have special meaning as commands/delimiters.
This encoding is natural. Fussing with entities only kicks in when you have
awkward characters. Further, the way you encode parameters is completely
familiar — almost the same way you encode awkward characters in HTML body
text. Watch out for &#xnnnn; and &#nnnn;
style entities. What they mean depends on the enclosing HTML document encoding.
Alternatively, you could write a little utility to use java.net.
URLEncoder to encode the string, then manually
include it as the param value, then use java.net. URLDecoder
inside the Applet to make sense of the parameter. URLEncoder
encodes space as + and special characters as %xx
hex, so you can do the encoding in your head once you see a few examples. The
catch is, once you hook up URLDecoder to a param,
you can’t use that param anymore for plain text, at least not completely
transparently.
If you wanted to disguise the value, you could encode it with base64
or base64u armouring. |
| <img src= "image/NoJava4U.jpg"
> |
image to display if no Java interpreter available. |
| You need Java to run this Applet |
Text that will display on a really stupid browser that has no idea what an Applet
tag is. |
| </applet> |
and finally the ending tag for the |
A minimal Applet invocation might look like this:
<applet code="MyApplet.class" width="330" height="240">
</applet>
Make sure you get your < ’s and >
’s in the right places.
A more typical Applet invocation might look like
this:
<applet
archive="../mypackage.jar"
code="com.mindprod.mypackage.MyClass.class"
width="565" height="46"
alt="Java needed to display this Applet.">
<param name="flavour" value="strawberry">
Java needed to display this Applet.
</applet>
To run Applets in Internet Explorer 5.5 or Netscape
4.79 with the old Java 1.3 Plugin before the courts smacked Microsoft for their
violation of their agreement with Sun, you need a hideously complicated syntax
using nested <OBJECT> and <EMBED>tags.
The best way to generate them is to use the HTML converter program on your
simple <applet tags. You don’t need them
to run with the Plug-in 1.4 in the recent versions of Opera, Mozilla, Firefox,
Netscape and IE. Further, the latest Mozilla can’t even understand them.
Their only advantage is they can arrange to install a Java JRE if one is not
installed already. I boycott them on the grounds of terminal ugliness.
<applet, from a CSS point of view, is just
another tag. In your CSS style sheet, you can apply properties to it, adjust the
margin spacing, put borders around it… In your HTML markup you can give
it a class or id. Unfortunately Mozilla, Netscape and Firefox all have a common
bug and don’t display a border around Applets
even when you ask them to. Opera and IE work properly.
<OBJECT> and <EMBED>
In theory, <applet has been deprecated and you
should use the more generic, verbose, error-prone <OBJECT
tag. <OBJECT has some minor nice features, like
a standby message and a way of providing alternate implementations if the user’s
browser does not support Java. It can work with serialised Applets.
It works for languages and plug-ins other than Java. However, <OBJECT
is still not as widely supported as <applet, so
it is probably wiser to stick with <applet. See
the HTML
spec for details.
That was the polite version, but here is what I really think of <OBJECT>
and <OBJECT> tags. Anti-Java, rather corrupt
people launched a successful attempt to derail Java by somehow convincing some
weak minded folk at the W3C to deprecate the <applet
tags. Browser makers have all sensibly resisted this foul play and all continue
to support <applet. The replacement is an
utterly preposterous and verbose scheme using <OBJECT>
and <OBJECT> tags that works in different
ways in different browsers. The scheme is beyond ridiculous. It is so baroque,
you can’t even hand code it. You have to use an automated tool to convert <applet
tags into pages and pages of gobbledegook. Don’t use them!
Tell the W3C and Microsoft to shove their <OBJECT>
and <EMBED> and lunatic classids
to a foul-smelling place. Please, do not use these tags!
You can use a simple
Jump
to Java Button to handle a missing JRE.
Switch Hitter: Applet ⇒ application
By adding the following method to your Applet, you
can allow it be run either as an Applet or as an
application. I call these dual mode programs hybrids
or switch hitters. If your Applet
were called MyApplet, here is the code to add to the MyApplet class to make it also
into an application:
Your Applet can get hold of the parameters in the HTML.
That code is quite crude. It will not do such things as:
- Simulate the getParameter method to get at the Applet
parameters.
- Adjust the co-ordinate system so part of the Applet
is not hidden under the Frame menu bar. Layout
managers deal with this automatically, but if you do absolute positioning, you
have to compensate manually..
- It does not simulate getAppletContext. Code
defensively to deal with a null return.
The easiest way to deal with these problems is to use two Applet
constructors, one the usual default constructor and one that passes the param
information in. Inside you can keep track of which mode you are running in with
a boolean you set in the constructor. getParameter(
"favouriteColour" ) will return the
String "orange" . When you write an Applet
often you will override some of the following methods: init(),
start() , stop() , destroy()
and paint(Graphics g).
There is equivalent code for JApplet.
Switch Hitter: application ⇒ Applet
What if you already have an application? how to you allow it to run also as an Applet?
An Applet is just a Panel
with init, start, stop
and destroy methods. Write an Applet
shell that does a this.add to add your application
into the Applet in its init
method, just as you would any other Panel.
Transparency
Though it is possible to create transparent and translucent components using
colours with the alpha channel ( the fourth number in new
Color ( red, green, blue, alpha )) set to something other than 0xff,
I have found no way to make the Applet or JApplet
itself transparent. You could pass the colour of the web page’s background
in as an Applet param or have JavaScript communicate
that information to Java. This would only give true transparency only when the
browser were using a plain untextured background.
Loading A Web Page
Often you want to display some other web page. You can trick the browser into
doing that for you with:
this.getAppletContext().showDocument( url, window );
Your Applet does not get to see the web page. It
goes straight to the browser for rendering. Because this feature can be so
easily abused to wallpaper the user’s screen with popups, it is now often
blocked.
InterApplet Communication
Communication between Applets running on the same
page, it turns out, is much simpler than you might imagine. First, there is only one
program per web page running. In fact there is only one program per browser
running. Applets are just a bunch of ordinary
objects. Applets from the same class share the same
static variables! Objects can call each other’s methods. They are all in
the same address space. There is thus almost zero problem with interApplet
communications. Your only problem is finding the other Applet
objects on your page to talk to. There are two mechanisms for that,
- Applet Applet.getAppletContext().getApplet(
"receiver" )
that accesses another Applet uniquely identified via
a name you assign in the HTML <applet name= tag.
- Applet Enumeration Applet.getAppletContext().getApplets()
that gets you a list of all the Applets, of any
class, not just yours, running on the page (including yourself).
An Applet propagates information around by putting
it in static variables, or by passing parameters to the methods of other objects
to get them to do something with the information. There is only one thread, not
one per Applet. You can’t just deposit
information and expect the other Applets to notice
the change.
The browser may decide to kill (forget) Applets not
on the current page, and then again it may not. Presumably, if you held onto a
reference to offscreen Applets in your onscreen Applet,
or in a common doubly linked object, those offscreen objects would have
to stay alive.
Applet Classpath
Applets use the ordinary local classpath. This can
cause trouble since the developer’s classpath and the end user’s
classpath won’t usually match. There are two sorts of trouble that ensue:
- If you have any classes not in a package, these non-uniquely named classes could
conflict with ones on the end-user’s local hard disk. To avoid this
problem, put any classes ever used by Applets in
some globally uniquely named package, e.g. com.mindprod.business
- You, as developer, may forget to include a necessary class in your jar, usually
from some peripheral package. It will work fine on your machine, but will fail
on the customer’s machine. On your machine, the JVM finds the missing
class via the classpath. On the end user’s machine that search fails.
- You as developer may test an Applet jar, yet
actually may be using some fresher classes on your local hard disk. You
inadvertently ship stale code.
On the other paw, the Applet classpath can work in
the developer’s favour. If an Applet requires
a huge support class library, he can ask the user to download and install it on
his local hard disk and point the classpath to it (or put it in the ext
directory). Then the class library will be immediately available every time the Applet
runs.
Applet vs Application
When you are starting a project, which should it be, an Applet
or application or both? The advantages of using an Applet
are:
- You can get the browser to render HTML for you.
- You can direct the browser to fetch and display material off the web.
- The user automatically gets the latest version of the software.
- There is nothing to install.
The disadvantages of using an Applet are:
- To do anything interesting, you must use signed Applets.
There are many different signing schemes to support. Signing is complicated.
- Applets must co-exist with a browser. There is less
RAM available to work.
- Applets must co-exist with a variety of browsers and
their variety of bugs and lack of support. IE supports only Java 1.14 with no
RMI, Swing, Collections etc. It is almost impossible to write code that dodges
all the bugs in all the browsers.
- Applets must be loaded over the Internet afresh each
time. This can be time consuming for fat ones. Modern browsers now cache Applets,
so this is no longer a disadvantage.
- Web Start is designed to distribute and update applications, not Applets.
- To start an Applet, you must first start a browser.
- You can’t use native code compilers on Applets,
only applications. This means your speed will be limited to the JVM supported by
the browser.
- You may not be able to force the user to update the browser to something recent.
There is a third possibility that has some of the advantage of both Applet
and application called Java Web Start.
Applet vs Servlet
The current fashion is to use Servlets exclusively
for all web based applications. I think this is idiotic. It has made data entry
even more primitive than it was on the keypunch. The advantages of using Applets
over Servlets are:
- With Applets, the user can find out about keying
errors right away, not with cryptic messages that appear only after you hit submit
and wait several seconds.
- With Applets, data entry can be much more
sophisticated, with keystroke validation, code lookup, pattern validation,
bounds checking, mandatory field validation, prompting, help etc.
- With Applets, data communications can go on in the
background and can be cached or procrastinated giving the illusion of instant
response.
- With Applets, you don't have to fill in a giant form
only to discover the server won't accept it.
- With Applets, you can run your applications on a
cheap vanilla HTML server. You don't need a complex, expensive to maintain, Servlet
womb.
- With Applets, you don't have to resort to dog's
breakfast kludges like Ajax to provide even tiny bits of
client side intelligence.
- With Applets, you have have sufficient local
intelligence to send much terser binary compressed messages back and forth with the
server. You can also exchange serialised Object trees.
The disadvantages of using Applets over Servlets
are:
- With Applets, a recent Java must be properly
installed at the client. This is more difficult to arrange than you might
imagine especially with the FUD from Sun's competitors spreading misinformation
about the danger of using Java when actually it is the safest language going.
- With Applets, you can't use low cost web designers
to help create your applications. With Servlets and
a framework markup language the designers don't have to write Java code, just
HTML, peppered with a bit of gibberish.
- With Applets that connect with a database, you need
a mixture of client size and server side code. This requires two sets of skills,
and keeping server and client size code in sync.
- Applets that do almost anything interesting have to
be digitally signed. This is an annoyance to users and frightens them off.
Splash Logo
In Java 1.5+ there is a splash logo that comes up as your Applet loads. It sort
of a radiant Sun-like image. You can modify that with a magic <param
tag that provides an alternate scalable image.
Applets can play *.au files,
(and *.wav files in Windows) this way:
Runtime Parameters
You can control the browser’s JVM runtime parameters (see java.exe)
that control stack and heap sizes etc. from the Java Control Panel. click
Start ⇒ Control Panel ⇒ Java ⇒ Java ⇒ Java Applet Settings ⇒
View . Add the required parameters in the 4th column, next to the JVM. It
does not look like it is editable, but it is.
Learning More
Sun’s Javadoc on the
Applet class : available: