Thankfully there are some good discussions and solutions by Drew McLellan and Florian Jenett. However, there are also a lot of people (including me) still having problems embedding applets in CMS pages from WordPress and Drupal, among others. Based on Drew and Florian’s articles, and with a fair bit of trial and error, you should now be seeing a large red interactive graph immediately below. If you can’t see this graph, then my solution is obviously completely wrong so you can save yourself some time by not reading any further…

Example Applet: This is an example of an embedded java applet.


Background

When I started, I had concerns about depending on <!--[if !IE]> <![endif]--> conditional comments within the HTML code to differentiate between browsers. I even wrote a related page about browser detection methods and concluded that, whilst a client-side option would probably have done what I wanted, I needed to be absolutely sure it would work even across browsers prior to IE5 and when Javascript may be disallowed.

I therefore decided to use server-side PHP for browser detection and serving pages with only the embedding code appropriate to the requesting browser. This seemed to be working absolutely fine most of the way through the development process, working mainly on a Mac and switching to my Windows machine for testing. However, I began to notice that, just occasionally, the applet wouldn’t load properly. Of course, even though I had site-wide caching disabled, it turns out that Drupal 6 still caches filtered content pretty aggressively and I had implemented my code as a filter module (most of my previous experience was with Drupal 4.7 and this was my first project with Drupal 6 in which this is a new feature).

Thus, the content being served to all subsequent browsers was the content generated for the very first bowser that had accessed it after a modification or cleared cache. Of course most of the time I’d be making changes and checking them in the same browser that prompted the change in the first place. On the occasions it didn’t load, I’d assume it was a local cache issue and just clear the cache.

Thus, for static web pages, the server-side PHP approach would work fine. Within a CMS server it’s a fight not worth having. Thus, I removed the browser detection switch and embedded the appropriate <!--[if !IE]> <![endif]--> conditional comments in the PHP output. The benefit is that the page content is always the same so is perfectly happy being cached.

Embedding an Applet

Based on templates created by Florian Jenett, the following is an xhtml1-strict standards compliant format for embedding a Java applet within all browsers except Microsoft Internet Explorer.

<object
  classid="java:appletName.class"
  type="application/x-java-applet"
  archive="/path/to/applet/appletName.jar"
  width="400"
  height="250"
  standby="Loading java applet..." >
  <param name="archive" value="/path/to/applet/appletName.jar" />
  <param name="mayscript" value="true" />
  <param name="scriptable" value="true" />
  <param name="image" value="loading.gif" />
  <param name="boxmessage" value="Loading java applet..." />
  <param name="boxbgcolor" value="#FFFFFF" />
  <param name="test_string" value="outer" />
</object>

The following is the xhtml1-strict standards compliant format for embedding a Java applet within Microsoft Internet Explorer.

<object
  classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
  codebase="http://java.sun.com/update/1.4.2/jinstall-1_4_2_09-windows-i586.cab"
  width="400"
  height="250"
  standby="Loading java applet..." >
  <param name="code" value="appletName" />
  <param name="archive" value="/path/to/applet/appletName.jar" />
  <param name="mayscript" value="true" />
  <param name="scriptable" value="true" />
  <param name="image" value="loading.gif" />
  <param name="boxmessage" value="Loading java applet..." />
  <param name="boxbgcolor" value="#FFFFFF" />
  <param name="test_string" value="inner" />

  <p>
    <strong>
      This browser does not have a Java Plug-in.<br />
      <a href="http://java.sun.com/products/plugin/downloads/index.html" title="Download Java Plug-in.">
      Get the latest Java Plug-in here.
      </a>
    </strong>
  </p>

</object>

Whilst most of it is the same, there are some important differences - the main ones being different attribute values. You can see that classid has two completely different values, codebase is added and archive removed. The value of the test_string param is different and IE requires an additional code parameter. Also, with IE it is possible to embed some HTML within the <object> </object> tags that is only displayed if the embedding fails.

Using Conditional Comments

In order to generate HTML that will work in both IE and all other browsers, it is possible to embed one <object> inside the pass-through code of another. Thus, if the first one works, you never see the second. As IE handles conditional comments and most other browser’s ignore them, you can make the outer object appropriate for non-IE browsers and wrap that in a conditional comment so that IE will ignore it. Then, place the IE-specific code inside the outer object - as shown below:

<!--[if !IE]> -->
  <object classid="appletName.class"
    type="application/x-java-applet"
    archive="appletName.jar"
    width="650" height="450"
    standby="Loading java applet - please wait..." >
    <param name="archive" value="/path/to/applet/appletName.jar" />
    <param name="mayscript" value="true" />
    <param name="scriptable" value="true" />
    <param name="image" value="/path/to/applet/loading.gif" />
    <param name="boxmessage" value="Loading java applet - please wait..." />
    <param name="boxbgcolor" value="#FFFFFF" />
    <param name="progressbar" value="true" />
    <param name="test_string" value="outer" />
<!--<![endif]-->
    <object classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
      codebase="http://java.sun.com/update/1.4.2/jinstall-1_4_2_09-windows-i586.cab"
      width="650" height="450"
      standby="Loading java applet - please wait..."  >
      <param name="code" value="appletName" />
      <param name="archive" value="/path/to/applet/appletName.jar" />
      <param name="mayscript" value="true" />
      <param name="scriptable" value="true" />
      <param name="image" value="/path/to/applet/loading.gif" />
      <param name="boxmessage" value="Loading java applet - please wait..." />
      <param name="boxbgcolor" value="#FFFFFF" />
      <param name="progressbar" value="true" />
      <param name="test_string" value="inner" />
    <p>
      <strong>
        This browser does not seem to have a Java plug-in.<br />
        <a href="http://java.sun.com/products/plugin/downloads/index.html" title="Download Java plug-in">
          Get the latest Java plug-in here.
        </a>
      </strong>
    </p>
  </object>
<!--[if !IE]> -->
  </object>
<!--<![endif]-->
  </object>

OpenGL for 3D Content

In order to embed a java applet that uses the JOGL OpengGL wrapper, you must actually run the JOGLAppletLauncher applet instead and pass the name and class of the actual applet you want as sub-applet parameters.

The following is an xhtml1-strict standards compliant format for embedding a JOGL Java applets using conditional comments.

<!--[if !IE]> -->
  <object classid="java:com.sun.opengl.util.JOGLAppletLauncher.class"
    type="application/x-java-applet"
    archive="appletName.jar"
    width="650" height="450"
    standby="Loading java applet - please wait..." >
  <param name="archive" value="/path/to/applet/appletName.jar" />
  <param name="mayscript" value="true" />
  <param name="scriptable" value="true" />
  <param name="image" value="/path/to/applet/loading.gif" />
  <param name="boxmessage" value="Loading java applet - please wait..." />
  <param name="boxbgcolor" value="#FFFFFF" />
  <param name="progressbar" value="true" />
  <param name="subapplet.classname" value="appletName" />
  <param name="subapplet.displayname" value="appletName" />
  <param name="test_string" value="outer" />
<!--<![endif]-->
    <object classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
      codebase="http://java.sun.com/update/1.4.2/jinstall-1_4_2_09-windows-i586.cab"
      width="650" height="450"
      standby="Loading java applet - please wait..."  >
    <param name="code" value="com.sun.opengl.util.JOGLAppletLauncher" />
    <param name="archive" value="/path/to/applet/appletName.jar" />
    <param name="mayscript" value="true" />
    <param name="scriptable" value="true" />
    <param name="image" value="/path/to/applet/loading.gif" />
    <param name="boxmessage" value="Loading java applet - please wait..." />
    <param name="boxbgcolor" value="#FFFFFF" />
    <param name="progressbar" value="true" />
    <param name="subapplet.classname" value="appletName" />
    <param name="subapplet.displayname" value="appletName" />
    <param name="test_string" value="inner" />
    <p>
      <strong>
        This browser does not seem to have a Java plug-in.<br />
        <a href="http://java.sun.com/products/plugin/downloads/index.html" title="Download Java plug-in">
          Get the latest Java plug-in here.
        </a>
      </strong>
    </p>
  </object>
<!--[if !IE]> -->
  </object>
<!--<![endif]-->
  </object>

Automatically Generating the Required Code

The above code is pretty laborious to type every time you need to embed an applet, and there is a lot of scope for error or omission in manual copy/paste operations. Thus, I opted to add a custom tag that I could add to the text of a document that could be parsed and converted to the format most appropriate to the requesting browser.

To embed custom data in a served page, I use my own [tag] construct using square brackets as these tend not to be used in standard writing and are database-friendly (which is exactly why WIKI text uses them). Also, rather than doing lots of different tests for many kinds of tag, I use a very simple yet flexible nomenclature of the form:

[tag=applet&size=600x700&title=An+example+embedded+java+applet.]AppletName[/tag]

This means that I can also use a fairly standard regular expression in PHP to parse and process all occurrences of [tag=XXX]Some HTML[/tag] pairs within any document text.

<?php
$text = preg_replace(
    '#\[tag=([\w:;&,%+~!=@\/\.\-\#\?]+?)\](.*?)\[/tag(?::\w+)?\]#sie',
    '_customModuleName_flexi_tag_callback(\'\\1\', \'\\2\')',
    $text
    );
?>

The callback function used above is detailed below. It gets passed two arguments: all the parameter text between the [tag= and the first ] brace; and then all the content text between the enclosing ] and [ braces. The key here is the use of the PHP parse_str() function which parses all the parameter text into an associative array of any ‘param=value’ pairs. This means that the text in the first argument needs to be formatted in exactly the same way as parameters in a HTTP GET command.

<?php
function _customModuleName_flexi_tag_callback($param_str, $content)
{

  // Some Drupal filter configurations get there first,
  // so best to change & back to & just in case...
  $param_str = str_replace("&amp;amp;", "&", $param_str);

  // Prepend 'tag=' before parsing to capture the
  // tag type within a $params['tag'] array entry.
  parse_str('tag=' . $param_str, $params);

  // Check for a java applet.
  if ($params['tag'] == "applet")
  {
    $params['applet'] = $content;
    return _customModuleName_embed_java_applet($params);
  }

  // Other detections here...

}
?>

Once we have the parameter array, the function that does the real work processes them into a formatted HTML <object> tag.

<?php
function _customModuleName_get_files_url()
{
  return "http://" . $_SERVER['HTTP_HOST'] . base_path() . file_directory_path();
}

function _customModuleName_embed_java_applet(&$applet)
{

  // Get the absolute URL of my 'applets' folder.
  $path = _customModuleName_get_files_url() . "/applets";

  // Check some values and set defaults.
  if (empty($applet['class'])) $applet['class'] = 'frame';
  if (empty($applet['message'])) $applet['message'] = "Loading java applet - please wait...";
  if (empty($applet['title']) && !empty($applet['caption'])) $applet['title'] = $applet['caption'];
  if (!empty($applet['size'])) list($applet['width'], $applet['height']) = explode('x', $applet['size']);
  if ($applet['height'] < 1) $applet['height'] = 250;
  if ($applet['width'] < 1) $applet['width'] = 400;

  // Wrap everything in a div.
  $output .= "<div class=\"" . $applet['class'] . "\">\n";

  // First object for non-IE.
  $output .= "<!--[if !IE]> -->\n";

  if ($applet['opengl'] > 0.5) $output .= "  <object classid=\"java:com.sun.opengl.util.JOGLAppletLauncher.class\"\n";
  else $output .= "  <object classid=\"java:" . $applet['applet'] . ".class\"\n";

  $output .= "    type=\"application/x-java-applet\"\n";
  $output .= "    archive=\"" . $applet['applet'] . ".jar\"\n";
  $output .= "    width=\"" . $applet['width'] . "\" height=\"" . $applet['height'] . "\"\n";
  $output .= "    standby=\"" . $applet['message'] . "\" >\n";

  $output .= "  <param name=\"archive\" value=\"{$path}/" . $applet['applet'] . ".jar\" />\n";
  $output .= "  <param name=\"mayscript\" value=\"true\" />\n";
  $output .= "  <param name=\"scriptable\" value=\"true\" />\n";
  $output .= "  <param name=\"image\" value=\"{$path}/loading.gif\" />\n";
  $output .= "  <param name=\"boxmessage\" value=\"" . $applet['message'] . "\" />\n";
  $output .= "  <param name=\"boxbgcolor\" value=\"#FFFFFF\" />\n";
  $output .= "  <param name=\"progressbar\" value=\"true\" />\n";

  // Check for opengl use.
  if ($applet['opengl'] != 0) {
    $output .= "  <param name=\"subapplet.classname\" value=\"{$path}/" . $applet['applet'] . "\" />\n";
    $output .= "  <param name=\"subapplet.displayname\" value=\"" . $applet['applet'] . "\" />\n";
    }

  $output .= "  <param name=\"test_string\" value=\"outer\" />\n";

  $output .= "<!--<![endif]-->\n";

  // Second object is for IE.
  $output .= "    <object classid=\"clsid:8AD9C840-044E-11D1-B3E9-00805F499D93\"\n";
  $output .= "      codebase=\"http://java.sun.com/update/1.4.2/jinstall-1_4_2_09-windows-i586.cab\"\n";
  $output .= "      width=\"" . $applet['width'] . "\" height=\"" . $applet['height'] . "\"\n";
  $output .= "      standby=\"" . $applet['message'] . "\"  >\n";

  if ($applet['opengl'] > 0.5) $output .= "    <param name=\"code\" value=\"com.sun.opengl.util.JOGLAppletLauncher\" />\n";
  else $output .= "    <param name=\"code\" value=\"" . $applet['applet'] . "\" />\n";
  $output .= "    <param name=\"archive\" value=\"{$path}/" . $applet['applet'] . ".jar\" />\n";
  $output .= "    <param name=\"mayscript\" value=\"true\" />\n";
  $output .= "    <param name=\"scriptable\" value=\"true\" />\n";
  $output .= "    <param name=\"image\" value=\"{$path}/loading.gif\" />\n";
  $output .= "    <param name=\"boxmessage\" value=\"" . $applet['message'] . "\" />\n";
  $output .= "    <param name=\"boxbgcolor\" value=\"#FFFFFF\" />\n";
  $output .= "    <param name=\"progressbar\" value=\"true\" />\n";

  // Check for opengl use.
  if ($applet['opengl'] != 0) {
    $output .= "    <param name=\"subapplet.classname\" value=\"{$path}/" . $applet['applet'] . "\" />\n";
    $output .= "    <param name=\"subapplet.displayname\" value=\"" . $applet['applet'] . "\" />\n";
    }

  $output .= "    <param name=\"test_string\" value=\"inner\" />\n";

  $output .= "    <p>\n";
  $output .= "      <strong>\n";
  $output .= "        This browser does not seem to have a Java plug-in.<br />\n";
  $output .= "        <a href=\"http://java.sun.com/products/plugin/downloads/index.html\" title=\"Download Java plug-in\">\n";
  $output .= "          Get the latest Java plug-in here.\n";
  $output .= "        </a>\n";
  $output .= "      </strong>\n";
  $output .= "    </p>\n";

  $output .= "  </object>\n";

  $output .= "<!--[if !IE]> -->\n";
  $output .= "  </object>\n";
  $output .= "<!--<![endif]-->\n";

  // Add caption and close wrapper div.
  if (!empty($applet['title'])) $output .= '<br /><span class="caption">' . $applet['title'] . '</span>';
  $output .= "</div>\n";
  return $output;

}
?>

You can find more details about using conditional comments within the Browser Detection Methods page.


Comments

1 July, 2011 - 18:50huyz

For WordPress, you can install the plugin that I just created for embedding Java applets using a shortcode. No coding required.

http://huyz.us/2011/the-easiest-way-to-embed-java-in-wordpress/


Click here to comment on this page.