<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Daniel Pitts' Tech Blog &#187; jsobject</title>
	<atom:link href="http://virtualinfinity.net/wordpress/tag/jsobject/feed/" rel="self" type="application/rss+xml" />
	<link>http://virtualinfinity.net/wordpress</link>
	<description>Daniel Pitts' Tech Blog</description>
	<lastBuildDate>Thu, 04 Feb 2010 19:10:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>JavaScript and Java applets</title>
		<link>http://virtualinfinity.net/wordpress/tools/2008/10/11/javascript-and-java-applets/</link>
		<comments>http://virtualinfinity.net/wordpress/tools/2008/10/11/javascript-and-java-applets/#comments</comments>
		<pubDate>Sat, 11 Oct 2008 18:32:37 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[applet]]></category>
		<category><![CDATA[bugs]]></category>
		<category><![CDATA[fixes]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jsobject]]></category>
		<category><![CDATA[work around]]></category>

		<guid isPermaLink="false">http://virtualinfinity.net/wordpress/?p=42</guid>
		<description><![CDATA[I know, Applets are almost dead, but we actually had use for them recently in a project.  We needed to upload multiple images at once, and since no one on our team knows Flash, we decided to use an Applet. Anyway, the trouble we came across was the Java to JavaScript bridge is flat-out broken.  [...]]]></description>
			<content:encoded><![CDATA[<p>I know, Applets are almost dead, but we actually had use for them recently in a project.  We needed to upload multiple images at once, and since no one on our team knows Flash, we decided to use an Applet.  Anyway, the trouble we came across was the Java to JavaScript bridge is flat-out broken.  What you are supposed to be able to do is well documented at <a title="Java-to-Javascript Communication" href="http://java.sun.com/javase/6/docs/technotes/guides/plugin/developer_guide/java_js.html" target="_blank">Sun&#8217;s java_js page</a> and <a title="LiveConnect Overview - MDC" href="http://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/LiveConnect_Overview" target="_blank">Mozilla&#8217;s LiveConnect page</a>.  The trouble is, that they are <em>wrong</em> when it comes to calling a Java method from JavaScript. They also fail to mention the security<strong></strong> implications of that altogether.</p>
<h2>Signed applets with unsigned JavaScript</h2>
<p>The first challenge we came to (which is actually the easiest to solve) was that we were getting AccessControlExceptions, even though we went through the trouble of <a title="Chapter 10: Signed Applets" href="http://java.sun.com/developer/onlineTraining/Programming/JDCBook/signed.html" target="_blank">signing the Applet jar</a>.  As it turns out, the permission context used is that of the JavaScript, so you need to elevate the permission to your Applets context, using <a title="AccessController (Java Platform SE 6)" href="http://java.sun.com/javase/6/docs/api/index.html?java/security/AccessController.html" target="_blank">AccessController</a>, and <a title="PrivilegedAction (Java Platform SE 6)" href="http://java.sun.com/javase/6/docs/api/index.html?java/security/PrivilegedAction.html" target="_blank">PrivilegedAction</a>.<br />
Java:</p>
<pre class="code java">public void javascriptCallsMe() {
    AccessController.doPrivileged(new PrivilegedAction() {
      public Void run() {
         // We can now
         readOrWriteFilesOrWhatever();
         return null;
      }
    });
 }</pre>
<p>That solved <em><strong>that</strong></em> problem.</p>
<h2>Passing JavaScript objects to Java</h2>
<p>The next problem, which plagued me for a week, was that getting a JSObject in Java seems to be broken.  There are two ways to get an instance of the netscape.javascript.JSObject class.  The first way, and this always seems to work, is the JSObject.getWindow(Applet applet).  This will get the JSObject wrapping the &#8220;window&#8221; browser object.  This is useful if you know the &#8220;path&#8221; to the JavaScript object your code cares about.  It is akin to using a static reference, and isn&#8217;t good design.  The other way, is to have a Java method that takes an Object or JSObject reference:  In Java:</p>
<pre class="code java">public class MyApplet extends JApplet {
  public void doStuff(JSObject params) {
    System.out.println(params.getMember("foo"));
  }
}</pre>
<p>Then in JavaScript you should be able to do this: <code class="code javascript">documents.applets[0].doStuff({foo: "bar"});</code> Unfortunately, what really happens is you get a &#8220;broken&#8221; instance of JSObject.  Debugging the Applet, I found that the JSObject instance has a field called nac, which has a value for the JSObject.getWindow(&#8230;), but is null for values passed in from JavaScript.  So, what solutions and work arounds have people come up with? None that I could find.  I searched high and low. Plenty of people have discovered this bug, but none of come up with a solution.  Until now!  I thought about it and realized, JSObjects I get from the &#8220;window&#8221; JSObject all work, so maybe I can put my broken object into a working object, and pull it back out to get a working object. A little experiment proved that it worked (at least on FireFox, I&#8217;ll guess it works on IE too, anyone want to verify?).  So, I decided to go ahead and create a JSObject resolver, that will fix any possibly broken object:</p>
<pre class="code java">public class MyApplet extends JApplet {
  private JSObject appletTmp;

  public JSObject resolveObject(Object o) {
    final int hashCode = System.identityHashCode(o);

    appletTmp.setMember("toResolve" + hashCode, o);
    return (JSObject) appletTmp.getMember("toResolve" + hashCode);
  }

  public void init() {
    if (appletTmp == null) {
      final JSObject window = JSObject.getWindow(this);
      final String tmpName = "_AppletTmp" + System.identityHashCode(this);
      window.eval("var "+ tmpName +" = {}");
      appletTmp = (JSObject)window.getMember(tmpName);
    }
  }
}</pre>
<p>Granted, this code doesn&#8217;t clean up after itself, so if you use it for a long time or on a lot of JS objects, you will need to add some clean up code to it.  With that, I was finally able to fully use the Java Applet the way I wanted to: As a &#8220;service provider&#8221; to the JavaScript on our existing page.</p>
]]></content:encoded>
			<wfw:commentRss>http://virtualinfinity.net/wordpress/tools/2008/10/11/javascript-and-java-applets/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
