Latest change: Sunday, 02-Jan-2011 16:13:02 CET


 
  de·caff MAIL to the Author

 
 


About this page

This page describes problems I observed when running Java Applets in different environments. For most of the problems workarounds are proposed. Some of the problems and workarounds described result from advices other people asked for. Thanks for your help!

I've tested with Netscape Navigator, Microsoft Internet Explorer and Sun's appletviewer as well as the Java Plugin from Sun. I do know nothing about Apple's implementation.

Hopefully the world is moving to the Java Plugin in the future, so we developers only have to test against one environment (still on different platforms, yuck).


Quickstart

General Tips
Bug hunting in Applets

Netscape Navigator
Cannot load resources from jar files
No mouse button while dragging
Last drawing command gets lost

Microsoft Internet Explorer
Applet is not showing

Sun
Drawing lines outside window

Common
Printing


 
Back to TOP de·caff MAIL to the Author

 



General Tips

What beginners often get wrong is using of the correct JDK version. Because the JVMs (Java Virtual Machines) of Netscape 4.x browsers and of all MSIE browsers only support the outdated 1.1.x version of the Java specification you should always develop your Applets with a JDK 1.1.x. It's still available from Sun, so get it. Compared to newer versions of the JDK version 1.1.x is very restricted, slow and ugly. Nevertheless, unless you are very sure that your Applet is such a hit that every potential user will download and install a newer JRE prior to using it: stick to JDK 1.1.x because it's the only one widely supported by default. Thank Microsoft for that.


What you can do when your Applet does not work as expected in browser XY?

So here you are: your Applet does not work and none of the problems and workarounds mentioned here or elsewhere matches your setting. What can you do?

Of course every problem is different but here's what I'd do (which is exactly the way I used to find the souces of the problems and the workarounds mentioned here:

  • My first step is to try with the appletviewer from Sun's JDK. Of course not any JDK but an 1.1.x one for reasons mentioned above. Because Sun's implementation sets a kind of standard and often gives useful error messages it's the 1st one where your applet should run.
  • Okay, appletviewer 1.1.x works fine (even with all restrictions switched on) but browser XY still gives only a useless message in the status line like "applet initialization failed". Now it's time for the Java console. Every browser out there has some kind of console (a window where messages from the virtual machine or your applet are printed and which often understands some keys for special commands like viewing the threads/stacks and starting garbage collection). In MSIE you have to switch it on in the options and restart it to find it in the Views menu, in Netscape it's in the Communicator>Tools submenu, with the Java plugin it's an extra window which can be switched on in the plugin settings.
  • Now start the console and look whether you find exceptions printed there. Usually you should try to understand them and fix the reasons for the exceptions. Some JVM implementations print security exceptions to the console even if they are explicitely catched in your code. If this is the case you may ignore them, of course.
  • No exceptions, but your Applet still does not work. Okay, back to the stone age of programming: insert useful System.out.println() debug statements at strategic positions in your code. This output goes to the Java console, too. This should help to get a grip on the problem, too. Sometimes new Throwable().printStackTrace(); lines are useful to see from where your methods are called.
  • That's all. You should be able to track the reasons for your problem this way at last (at least I always managed to do so). As mentioned above, some Java consoles allow for special commands which are usually shown at the beginning of the console output. Just read what's printed there.


 
Back to TOP de·caff MAIL to the Author

 



Problems when running under the Netscape Java Virtual Machine

Because I am doing my implementation work on Linux Netscape's Navigator is always one of the first test cases for my Applets. So I know a lot of it's errors. Indeed I usually have Java switched off when I surf the net because Navigator often freezes when running Applets, especially for low bandwidth connections.

The support of LiveConnect, i.e. the connection between Applets and JavaScript is still a lot better in Navigator than in MSIE.

I haven't tried Navigator 6.0 yet because I didn't hear much good of it. But as far as I know it's using the Java Plugin from Sun, so the following problems should no longer occure.


PROBLEM: Navigator cannot download resources from jar files.


DESCRIPTION

Your jar archives do not only contain class files, they contain other resources as well: images, helpfiles etc. The problem is, when running in Navigator the Applet is not able to access this files.


OCCURENCE

All Navigator 4.x versions on all platforms I've tested so far.


WORKAROUND #1: Convert resources to class files

One possibility is to convert your resources to class files. For text's this is really simple, for images there are some free conversion tools to be found on the net.

Beneath the more complicated handling (internally and when changing resources) there's one major drawback: the Java virtual machine specification states that methods may not be bigger then 64 kByte. And because even initializers are converted to methods in the compilation process, this means that your data may not exceed 64 kByte (minus some for the initialization code). So this works only for small resources like icons.


WORKAROUND #2: Add your resources to the server.

For this workaround you have to be sure to load the resources via an absolute path. I.e. each resource path must start with a /.

Now add your resources to a matching directory under the codebase of your server. E.g. if your code looks like:

private void loadIcons()
{
  teapot = new ImageIcon(getClass().getResource("/images/teapot.gif"));
}
    

if you put the file teapot.gif in a directory images under your codebase (as defined by the applet tag).


PROBLEM: Navigator reports no mouse button while dragging.


DESCRIPTION

In the mouseDragged method of a MouseListener the getModifiers() method of the event returns 0.


OCCURENCE

Navigator 4.x on Windows platform.


WORKAROUND: Assume button 1 is pressed

Code example:

public void mouseDragged(MouseEvent e) {
    int modifiers = e.getModifiers();
    if (modifiers == 0) {
      // workaround for old netscape bug on windows
      modifiers = MouseEvent.BUTTON1_MASK;
    }
    // ... your code here ...
}
    

By the way: if you are concerned about portability you should should alway support another means of input despite different mouse buttons, because Apple Macintosh users still have only one, i.e. pressing the "left" mouse button and some modifier key like Shift.


PROBLEM: Navigator sometimes does not show the last thing your app drawed to a Graphics.


DESCRIPTION

In something like an overwritten paint() method you do some special drawing. The last thing you draw is not shown.

I discovered that error when drawing a zoom rectangle while the users dragged the mouse and I suspect the dragging is part of the problem. The rectangle wasn't drawn when the mouse was stopped (still dragging), but it was drawn while the mouse was moving during the drag operation and when it was released (even if there was not drawing code toggled by the mouseReleased() method).


OCCURENCE

Navigator 4.x on Windows platforms.


WORKAROUND: Draw twice

Because this workaround is somewhat obscure I'm adding some code to my applets to be sure only to use it for Netscape on Windows.

Here's a code example:

// At class level:
  /** Windows netscape has some obscure bugs. */
  private final static boolean WIN_NETSCAPE_WORKAROUND = 
    System.getProperty("os.name").startsWith("Win")  &&
    System.getProperty("java.vendor").startsWith("Netscape") &&
    System.getProperty("java.version").startsWith("1.1");
   
// ...

  public void paint(Graphics g) {
      // ...

      g.drawRect(x, y, w, h);
      if (WIN_NETSCAPE_WORKAROUND) {
	  // Windows Netscape 4.x needs another draw...
	  g.drawRect(x, y, w, h);
      }
  }    
  
    

 
Back to TOP de·caff MAIL to the Author

 



Problems when running under the Microsoft Java Virtual Machine

Looking back it seems as Microsoft has won the browser war, seemingly using dirty tricks.

But as they've announced their Java engagement canceled I'm wondering how they are planning to support Java in Internet Explorer in the future. Still using their own Virtual Machine or switching to direct support of the Java plugin? I would prefer the latter because that would mean less implementation and testing effort for developers.

The Microsoft Java Virtual Machine is fast, but does not support all features the others do. At least LiveConnect is a lot more restricted, e.g. there's no support for arrays.


PROBLEM: The Applet starts but there's only a grey rectangle visible.


DESCRIPTION

Your Applet builds it graphical representation in the init() method and everything works fine with other browsers. But using MSIE you only see a grey rectangle.


OCCURENCE

MSIE 4.x and 5.x


Workaround 1: Add center components to BorderLayout containers explicitely

Try this workaround first. It has often helped me.

MSIE seems to have problems with BorderLayout if you add a component to the center using the implicite default, i.e. you just say:

  add(anyComponent);
    

Use the explicite version of add instead (for all containers with BorderLayout, but especially for the Applet itself:

  add(anyComponent, BorderLayout.CENTER);
    


WORKAROUND 2: Set the size of the Applet to the size it has

At the end of the init() method (or whereever you've constructed all components and added them to the Applet container) add a line:

  setSize(getSize());
    

May look funny, but give it a try.

Alas: this workaround does not always help. Main problem seems to be a race condition in Microsoft's applet code. Dejan Jelovic provides an deeper analysis of the problem on his web page.




 
Back to TOP de·caff MAIL to the Author

 



Problems when running under the Sun Java Virtual Machine

The JVM of Java's creators is of course some kind of standard. Not that it does not have bugs, but at least Sun is publishing them in their Bug Parade where you can find problem descriptions and sometimes even workarounds. To view the Bug Parade you've to become a member of the Java Developer Connection, but if you are earnest with Java, I would strongly recommend that anyway.


PROBLEM: Drawing lines with endpoints far outside the window give random results and can even freeze the complete virtual machine.


DESCRIPTION

If you draw lines (using the drawLine() or drawPolyline() method of the java.awt.Graphics class) and the start and/or end point is far outside the window (i.e. the absolut value of them is large compared to the window size) the lines are not properly clipped but drawn randomly across the window. In newer releases it may even freeze the complete Java Virtual Machine.

This is bug number 4252578 in the bug parade. It is not especially an Applet but but may occure in any circumstances using Sun's JVM.

Meanwhile Sun marked this bug as closed for Java 1.4 but at least in Java 1.4.0 under Linux it's still there...


OCCURENCE

Drawing criss-cross lines: all versions on all platforms
JVM freezes: version 1.2 and 1.3 on all platforms


WORKAROUND: Don't draw such lines

To make that easier you may use a clipping class I have implemented. You can find it on this ugly page.




 
Back to TOP de·caff MAIL to the Author

 



Common Problems or Problems which involve combined workarounds for several browsers

At the moment this chapter only handles one very dark area: printing. Generally the Java sandbox does not allow an Applet to print directly to the printer. If you are after that, you'll have to create a signed Applet, which is not handled here.

What is possible is to print something from your Applet when the user prints the page (via File>Print) or frame where your Applet is in.


PROBLEM: You want your Applet to print something when the browser prints the page/frame you're Applet is running in.

Theory

In theory you'll have to do nothing. When the page is printed, the browser calls the printAll(Graphics) method of your Applet with a PrintGraphics of some kind. The default behaviour is to paint everything to the given Graphics, so your Applet should just paint itself to the printer like it paints to the screen.

Reality

Of course you're doomed if you rely on the above scheme. Printing is a dark chapter in Java 1.1 anyway (even if it works it's ugly because it's a better kind of hardcopy where each pixel get's 1/72 inch big), but browsers implementation of the necessary environment is nearly as obfuscated as can be.

Here are the main problems I observed so far (I'll handle only Netscape 4.x and MSIE 5.x/6.x here, because with the Java plugin you should switch to 1.2 printing as soon as possible):

  • MSIE:
    Instead of calling the printAll method of the Applet running in the browser page MSIE creates a completely new Applet and calls it's printAll method. So you'll always see the initial state of your Applet printed, because the new Applet knows nothing about any state changes (e.g. due to user interaction) happened in the original Applet.
  • Netscape:
    Netscape fails to initialize the Graphics with useful defaults: it does neither set a clipping area nor a default font, so if your Applet uses Font interaction, you'll get NullPointerExceptions. Furthermore on Windows the size the Applet has in the page is only 75% of the original size (this is a heuristic value, because, as mentioned before, the clipping area is unset and you have no means of getting the size where to print to).

What to do

Here's the rules I use to handle printing:

  1. Overwrite the Applet's printAll(Graphics) so it calls print(Graphics).
  2. Create a private method called realPrint(Graphics) where you handle printing like you want.

    Usually it's a good idea to print your Applet different from what you see when it's drawn on the page, because there's no need to print something like buttons and other GUI components. And in most cases it's preferable to print to a white background, even if the Applet looks otherwise.

  3. The first thing to do in the realPrint(Graphics, ...) method is to work around the Netscape problem with the unset default values. Set a font and a clipping area here. If really running on Netscape the Clipping rectangle should be 75% of the Applet's size.
  4. Print everything as you like in realPrint(). Your printing algorithm has to be able to print to an area with another size than that of the original applet because the clipping area will have different sizes in different browsers.
  5. Create a standard print(Graphics) method which handles the obscure MSIE bug by checking whether the Applet is run in MSIE, looking for another Applet with the same class and, if successfull, call the realPrint() method of that Applet.

    As default just call realPrint() directly.

I agree that this sounds very theoretically, so I created a simple Applet which obeys the rules above:

  1. Run the applet
  2. Download source

 
Back to TOP de·caff MAIL to the Author