Sunday 23 November 2008

Applet <-> Javascript integration

It's been a while since I've done this, but I thought I'd refresh my memory on the options available. Maybe Applets have fallen out of favour a bit and whilst Javascript is popular for Rich, Dynamic Internet Applications, sometimes you need more and one way to do it is to use Applets, or integrate Applets with Javascript.

This example shows some simple ways to achieve Applet/JavaScript integration:

I've included example HTML with JavaScript source and Java source code for an Applet, to demonstrate so ways to achieve JavaScript to Java Applet integration. The simple example code demonstrates both JavaScript calling a Java Applet and a Java Applet calling JavaScript.

The JavaScript function jsShowMsg(String) is called in two different ways from the Java Applet. A single string parameter is passed, and the JavaScript function displays this using the standard alert() function to create a dialog box.

The Applet provides a showMessage(String) public method, which similarly is called by the JavaScript code when the button on the page is pressed. The String parameter is taken from the text field and displayed in the Applet.

HTML Page:


Provides the Applet on the page. Provides the JavaScript function called by the Applet, calls the Applet public method when the button is clicked (takes the String value from the input text box.

--

<HTML>
<HEAD>
<TITLE>Applet HTML Page</TITLE>
</HEAD>
<BODY>
<script type="text/javascript">

/**
* jsShowMsg - demostrates being called by an Applet, being passed a single String argument, the message
*/
function jsShowMsg(msg)
{
alert("Message from applet was: '" + msg + "'");
}

/**
* callApplet - demonstrates calling a public method on the Applet (showMessage(String))
*/
function callApplet(msg)
{
//alert("before calling Applet method with msg=" + msg);

document.testApplet.showMessage(msg);

//alert("after calling Applet method");
}
</script>

<H3><HR WIDTH="100%">Applet HTML Page - Applet <-> JavaScript integration example<HR WIDTH="100%"></H3>

<P>
<APPLET name="testApplet" codebase="classes" code="com/chillipower/TestApplet.class" width=400 height=150></APPLET>
</P>

<input type="text" id="msgTb" name="msgTb" value="A message from JS!" /><input type="button" value="button1" onclick="callApplet(getElementById('msgTb').value);" />

</BODY>
</HTML>

--


Java Applet Class:


Calls the JavaScript function in two different ways when the Applet is started. Provides a showMessage public method that the JavaScript can call.

--

package com.chillipower;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;

/**
* @author Louis B
*/
public class TestApplet extends Applet
{
String JS_MESSAGE = "Hello from Java Applet to JavaScript (using JavaScript alert)";
String JS_FUNC_NAME = "jsShowMsg";


/**
* init - applet init function
*/
@Override
public void init()
{
setBackground(new Color(0xFAFAFF));
}

/**
* start - applet start function
*/
@Override
public void start()
{
callJsByProto(JS_FUNC_NAME, JS_MESSAGE + " using showDocument :javascript protocol method");

callJsFunc(JS_FUNC_NAME, JS_MESSAGE + " using JSObject method");
}

/**
* Overide paint with simple text rendering
*
* @param g
*/
@Override
public void paint(Graphics g)
{
g.drawString("The Applet", 20, 20);
}

/**
* Simple function to show a message
*
* @param msg
*/
public void showMessage(String msg)
{
Graphics g = getGraphics();
g.setColor(Color.RED);
g.drawString("Message from JS: '" + msg + "'", 20, 40);
}

/**
* Call a named JS function, passing a single String parameter
*
* @param funcName
* @param msg
*/
private void callJsByProto(String funcName, String msg)
{
try
{
getAppletContext().showDocument
(new URL("javascript:" + funcName + "(\"" + msg +"\")"));
}
catch (MalformedURLException ex)
{
System.out.println("ex: " + ex.getMessage());
}
}

/**
* callJsFunc - call the named JavaScript function, passing the String msg argument
*
* @param funcName
* @param msg
*/
private void callJsFunc(String funcName, String msg)
{
String jscmd = funcName + "('" + msg + "')"; // Buiild the JavaScript command
String jsresult = null;
boolean success = false;

try
{
Method getw = null;
Method eval = null;
Object jswin = null;
Class c = Class.forName("netscape.javascript.JSObject"); /* works in IE too */
Method ms[] = c.getMethods();

for (int i = 0; i < ms.length; i++)
{
if (ms[i].getName().compareTo("getWindow") == 0)
{
getw = ms[i];
}
else if (ms[i].getName().compareTo("eval") == 0)
{
eval = ms[i];
}
}

Object a[] = new Object[1];
a[0] = this; /* this is the applet */
jswin = getw.invoke(c, a); /* this yields the JSObject */
a[0] = jscmd;
Object result = eval.invoke(jswin, a);

if (result instanceof String)
{
jsresult = (String)result;
}
else
{
jsresult = result.toString();
success = true;
}
}
catch (InvocationTargetException e)
{
jsresult = e.getTargetException().getMessage();
}
catch (Exception e)
{
jsresult = e.getMessage();
}

if (success)
{
System.out.println("JS eval succeeded, result is " + jsresult);
}
else
{
System.out.println("JS eval failed with error " + jsresult);
}
}
}

Debugging:

1. Using the Java ControlPanel (on 'nix, it is View Settings -> Edit the Java Runtime settings.

-agentlib:jdwp=transport=dt_socket,address=:

This makes the browser plug-in JRE open a debugging socket connection when launching the applet.

2. Open the Netneans project and attach the debugger in the SocketListen mode, using the same settings as above.



Resources:

http://windyroad.org/2006/08/14/reintroducing-javascript-and-hidden-applets-jaha/

http://java.sun.com/javase/6/docs/technotes/guides/plugin/developer_guide/java_js.html


.

No comments: