Exercise 2: Programming with LiveConnect: Bridge between Java/Java FX and JavaScript
(40 minutes)
This exercise shows APIs of LiveConnect, and examples of using those APIs to
interact between Java/Java FX and JavaScript/DOM objects in the same web page.
Background Information
Introducing the LiveConnect bridge
Since Java SE 1.4, applet developers have been able to
traverse the Document Object Model (DOM) of the document containing
their applet using the Common DOM API. The Common DOM implementation
has been rewritten and simplified in the new Java Plug-In, and is now
both more robust and easier to use.
The bridge between the Java and JavaScript programming
languages, known informally as LiveConnect, has been reimplemented. The
new implementation is backward-compatible and features improved
reliability, performance and cross-browser portability, for both Java
calling JavaScript as well as JavaScript calling Java. Formerly
Mozilla-specific LiveConnect functionality, such as the ability to call
static Java methods, instantiate new Java objects and reference
third-party packages from JavaScript, is now available in all browsers.
A new LiveConnect specification both documents the behavior of the
Java/JavaScript bridge in the new Java Plug-In, and specifies how
alternate implementations of a Java Plug-In should behave to support
portability of mixed Java/JavaScript code.
Steps to Follow
- Click the Files Tab in the NetBeans IDE, and then expand
the HelloApplet Node.

- Double-click the 'DomApplet.java' and implement method actionPerformed() as shown in the following box.
1 /* 2 * To change this template, choose Tools | Templates 3 * and open the template in the editor. 4 */ 5 package demo.applets; 6 7 import com.sun.java.browser.plugin2.DOM; 8 import java.awt.FlowLayout; 9 import java.awt.event.ActionEvent; 10 import java.awt.event.ActionListener; 11 import javax.swing.JApplet; 12 import javax.swing.JButton; 13 import org.w3c.dom.Attr; 14 import org.w3c.dom.html.HTMLDivElement; 15 import org.w3c.dom.html.HTMLDocument; 16 17 /** 18 * 19 * @author jason 20 */ 21 public class DomApplet extends JApplet implements ActionListener { 22 23 JButton button1 = new JButton("Change Title"); 24 JButton button2 = new JButton("Hide text"); 25 JButton button3 = new JButton("Show text"); 26 27 @Override 28 public void init() { 29 super.init(); 30 button1.addActionListener(this); 31 button2.addActionListener(this); 32 button3.addActionListener(this); 33 this.getContentPane().setLayout(new FlowLayout()); 34 this.getContentPane().add(button1); 35 this.getContentPane().add(button2); 36 this.getContentPane().add(button3); 37 } 38 39 public void actionPerformed(ActionEvent e) { 40 // Set the title of the HTML page containing this applet 41 Object source = e.getSource(); 42 if (source == button1) { 43 HTMLDocument document = (HTMLDocument) DOM.getDocument(this); 44 document.setTitle("Title By Applet"); 45 46 } else if (source == button2) { 47 //hide it 48 HTMLDocument document = (HTMLDocument) DOM.getDocument(this); 49 HTMLDivElement div = (HTMLDivElement) document.getElementById("testdiv"); 50 Attr myAttr = div.getAttributeNode("style"); 51 System.out.println("style value:" + div.getAttributeNode("style").getValue()); 52 myAttr.setValue("visibility:hidden"); 53 div.setAttributeNode(myAttr); 54 } else if (source == button3) { 55 //show it 56 HTMLDocument document = (HTMLDocument) DOM.getDocument(this); 57 HTMLDivElement div = (HTMLDivElement) document.getElementById("testdiv"); 58 Attr myAttr = div.getAttributeNode("style"); 59 System.out.println("style value:" + div.getAttributeNode("style").getValue()); 60 myAttr.setValue("visibility:visible"); 61 div.setAttributeNode(myAttr); 62 } 63 } 64 }
Note: the key point in the above code is line 43, 48 and 56.
In the new plugin implemetation, the bootstrapping mechanism for
acquiring the the Document object has been simplified. There is now one
simple entry point which can be called from any thread:
package com.sun.java.browser.plugin2;
public class DOM {
public static final
org.w3c.dom.Document getDocument(Applet applet)
throws org.w3c.dom.DOMException;
}
An applet may call this method as follows:
org.w3c.dom.Document document =
com.sun.java.browser.plugin2.DOM.getDocument(this);
After getting the Document object, we can cast it into a HTMLDocument,
and generally use any of the APIs in the org.w3c.dom namespace.
For the detail DOM api, please refer to this page:
http://java.sun.com/javase/6/docs/jre/api/plugin/dom/index.html.
-
Double click the file 'dom-applet.html' shown below.

- Modify the code for file ' dom-applet.html' as shown in the
following table.
1 <!-- 2 To change this template, choose Tools | Templates 3 and open the template in the editor. 4 --> 5 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 6 <html> 7 <head> 8 <title></title> 9 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 10 </head> 11 <body> 12 <script src="deployJava.js"></script> 13 <script> 14 var attributes = {codebase:'.', 15 code:'demo.applets.DomApplet.class', 16 width:200, height:200, 17 archive: 'dist/HelloApplet.jar', 18 id:'DomApplet', 19 name:'DomApplet', 20 mayscript:'false'} ; 21 var parameters = {fontSize:16,draggable:'true',classloader_cache:'false'} ; 22 var version = '1.6' ; 23 deployJava.runApplet(attributes, parameters, version); 24 </script> 25 26 <hr/> 27 <div id="testdiv" style="visibility:visible"> 28 These are some words.... 29 </div> 30 </body> 31 </html>
-
Run the Applet in browser.
Open the file explore and navigate to the directory containing the file
launch-with-applet-tags.html and then double click the file, the applet
will run in the browser as shown below.

Try to click the button in the applet and see the effect in the browser.
-
Click the Files Tab in the NetBeans IDE, and then expand
the HelloApplet Node.

- Double-click the file 'HelloApplet.java' shown above and
modify the code as following table.
1 /* 2 * To change this template, choose Tools | Templates 3 * and open the template in the editor. 4 */ 5 package demo.applets; 6 7 import java.applet.Applet; 8 import java.awt.FlowLayout; 9 import java.awt.event.ActionEvent; 10 import java.awt.event.ActionListener; 11 import java.awt.event.MouseEvent; 12 import javax.swing.JApplet; 13 import javax.swing.JButton; 14 import javax.swing.JTextField; 15 import netscape.javascript.JSObject; 16 17 /** 18 * 19 * @author jason 20 */ 21 public class HelloApplet extends JApplet implements ActionListener { 22 23 JButton button = new JButton("Hello"); 24 JButton button2 = new JButton("Call JavaScript"); 25 JTextField name = new JTextField(10); 26 27 @Override 28 public void init() { 29 //set event handler 30 button.addActionListener(this); 31 button2.addActionListener(this); 32 //add widget to the applet 33 34 this.getContentPane().setLayout(new FlowLayout()); 35 this.getContentPane().add(name); 36 this.getContentPane().add(button); 37 this.getContentPane().add(button2); 38 } 39 40 public void actionPerformed(ActionEvent e) { 41 Object target = e.getSource(); 42 System.out.println("Button clicked"); 43 if (target == button) { 44 System.out.println("You input:" + name.getText()); 45 Applet a = this.getAppletContext().getApplet("WorldApplet"); 46 WorldApplet wa = (WorldApplet) a; 47 wa.setLabelText(name.getText()); 48 } else if (target == button2) { 49 System.out.println("You click call javascript"); 50 JSObject win = JSObject.getWindow(this); 51 System.out.println(win.call("f", null)); 52 } 53 54 } 55 56 public String getNameValue() { 57 System.out.println("getNameValue called"); 58 return name.getText(); 59 } 60 61 public void setLabelText(String value) { 62 System.out.println("setLabelText called"); 63 } 64 65 public boolean isAppletDragStart(MouseEvent e) { 66 // Change the drag gesture to be left-click and drag with 67 // no modifier keys 68 System.out.println("isAppletDragStart "); 69 return (e.getSource() == this && e.isAltDown()); 70 } 71 72 }
Note:
The function of the above codes from line 50 to 51 is to call the
JavaScript method defined in the same HTML page, and line 45 to 47 is
used to call the method defined other applets.
HelloApplet applet above get the reference to WorldApplet by calling
this method (line 45) :
Applet a =
this.getAppletContext().getApplet("WorldApplet");
Where the "WorldApplet" is the
value of name attribute of the
WorldApplet deployed in step 6 below.
For more information, please refer to this page:
http://java.sun.com/javase/6/webnotes/6u10/plugin2/liveconnect/index.html.
- Double-click the file 'WorldApplet.java' shown below

- Modify the code as following table.
1 /* 2 * To change this template, choose Tools | Templates 3 * and open the template in the editor. 4 */ 5 6 package demo.applets; 7 8 import javax.swing.JApplet; 9 import javax.swing.JLabel; 10 11 /** 12 * 13 * @author jason 14 */ 15 public class WorldApplet extends JApplet { 16 JLabel label = new JLabel("This is an world applet."); 17 18 @Override 19 public void init() { 20 this.getContentPane().add(label); 21 } 22 23 public void setLabelText(String value) { 24 label.setText(value); 25 } 26 }
Note: This applet just contains a label, and provides method setLabelText to change the text on
the label.
- Double-click on the file 'demo.html' shown below.

- Modify the code for demo.html as shown in the table below.
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 2 <html> 3 <head> 4 <title></title> 5 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 6 <script src="deployJava.js"></script> 7 <script language="javascript"> 8 function go1() { 9 var value1 = HelloApplet.getNameValue(); 10 WorldApplet.setLabelText("Value from HelloApplet: " + value1); 11 } 12 13 function go2() { 14 var value1 = form1.foo.value; 15 WorldApplet.setLabelText("Value from HTML Form: " + value1); 16 } 17 18 function f() { 19 window.alert("abc"); 20 return "abc"; 21 } 22 </script> 23 </head> 24 <body> 25 <table border="1"> 26 <tr> 27 <td>Applet 1</td> 28 <td>HTML FORM</td> 29 <td>Applet 2</td> 30 </tr> 31 <tr> 32 <td> 33 34 <script> 35 var attributes = {codebase:'.', 36 code:'demo.applets.HelloApplet.class', 37 width:200, height:200, 38 archive: 'dist/HelloApplet.jar', 39 id:'HelloApplet',name:'HelloApplet', 40 mayscript:'false'} ; 41 var parameters = {fontSize:16,draggable:'true'} ; 42 var version = '1.6' ; 43 deployJava.runApplet(attributes, parameters, version); 44 </script> 45 </td> 46 <td> 47 <form name="form1"> 48 JavaScript Button: <input type="button" value="Put Applet 1 Value to Applet 2" onclick="go1()"/> 49 <br/> 50 <hr/> 51 <input name="foo" size="10"/> <input type="button" value="Put form Value to Applet 2" onclick="go2()"/> 52 </form> 53 </td> 54 <td> 55 56 <br/> Applet deployed with deployment tools: <br/> 57 <script> 58 var attributes = {codebase:'.', 59 code:'demo.applets.WorldApplet.class', 60 width:200, height:200, 61 archive: 'dist/HelloApplet.jar', 62 id:'WorldApplet',name:'WorldApplet'} ; 63 var parameters = {fontSize:16} ; 64 var version = '1.6' ; 65 deployJava.runApplet(attributes, parameters, version); 66 </script> 67 68 </td> 69 <tr/> 70 </table> 71 72 </body> 73 </html>
Note:
In the JavaScript code above (line 8 to 16), we call the methed of
applet via the name of the
applet. For example, line 9 in the above html page, var value1 =
HelloApplet.getNameValue(); will call the method getNameValue of the applet named HelloApplet which is deployed in
line 34 to line 44.
- Run the Applet in browser.
Open the file explore and navigate to the directory containing the file
demo.html and then
double click the file, the applet
will run in the browser as shown below.

In the above image, there are 3 parts. The left one is a Applet named
Applet 1, the middle part is just a HTML form and in the right is a
Applet named Applet 2.
Note:
- Click Hello
button in Applet 1 will send text from Applet 1 to Applet 2.
- Click 'Call JavaScript'
Button in Applet 1 will call javaScript method defined in this HTML
page.
- Click 'Put Applet 1
Value to Applet 2' in the HTML form will get the value in the
textfield in Applet 1 and then put the value into the Applet 2.
- Click ´Put form
Value to Applet 2´ in the HTML form will put the value in
the textfield in the form into the Applet 2.
In this step, we are going to access Java FX variables and call Java FX methods from JavaScript.
- Open LoveLetter project in Netbeans.
Double click Letter.fx to open it in the editor window. Let's study the code a little bit.
In Letter.fx, we define two sprites: smurf and smurfette, by the following code.
def smurf: Node = ImageView {
x: (fwidth) / 2,
y: (fheight - smurfh) / 2
image: Image {
url: "{__DIR__}smurf.png"
}
onMouseClicked: function( e: MouseEvent ):Void {
beating.play();
}
}
def smurfette: Node = ImageView {
x: 10,
y: 10
image: Image {
url: "{__DIR__}smurfette.png"
}
onMouseClicked: function( e: MouseEvent ):Void {
sendRose();
}
effect: PerspectiveTransform {
......
}
}
And a few images representing different status of the heart of smurf
def heartarrow: Node = ImageView {
......
image: Image {
url: "{__DIR__}heartarrow.png"
}
}
def heartbroken: Node = ImageView {
......
image: Image {
url: "{__DIR__}heartbroken.png"
}
}
def heartflying = ImageView {
......
image: Image {
url: "{__DIR__}heartflying.png"
}
}
def hearts: Node = Group {
content: [
heart,
heartarrow,
heartbroken,
]
}
Animations like heart beating, moving the rose, fadein, fadeout, etc. and functions
to play them.
var beating = ScaleTransition {
byX: 1.1,
byY: 1.1
node: hearts
duration: bind beatingRate
repeatCount: Timeline.INDEFINITE
}
......
function fadeIn(node: Node) {
FadeTransition {
toValue: 1.0
duration: 1.0s
node: node
}.play();
}
function fadeOut(node: Node) {
FadeTransition {
toValue: 0.0
duration: 1.0s
node: node
}.play();
}
public function fallInLove() {
fadeOut(heart);
fadeOut(heartbroken);
fadeIn(heartarrow);
}
public function heartBroken() {
fadeOut(heart);
fadeOut(heartarrow);
fadeIn(heartbroken);
}
......
public function sendRose() {
fadeIn(rose);
TranslateTransition {
fromX: 320,
fromY: 230
toX: 80,
toY: 50
node: rose
duration: 3s
interpolate: Interpolator.EASEBOTH
}.play();
}
-
Now, you've already had some ideas of the FX code, let's take a look at the HTML page where
we deployed the FX application onto in the previous execise.
Open MyLoveLetter.html in the <lab_root>/javaseclient/execise/page/ directory with an editor. The HTML file contains
a love letter from smurf to the smurfette. And if we move the mouse over the words"HARD", "LOVE" in the
letter, or click the words "ROSES", "MARRY", callback methods are called as following
......
<script>
function beating() {
//TODO: access beating variable of Java FX
}
function fallInLove() {
//TOOD: call fallInLove() method of Java FX
}
function sendRose() {
//TODO: call sendRose() method of Java FX
}
function willYouMarry() {
//TODO: call willYouMarryMe() method of Java FX
}
......
</script>
......
<p><img src="images/message.png" onClick="MM_showHideLayers('layerletter','','show','layerletter-yes','','hide','layerletter-no','','hide')"></img></p>
<div style="position: absolute; width: 100px; height: 100px; z-index: 1; left: 610px; top: 67px; visibility: hidden;" id="layerletter">
<p><img src="images/letter.png" name="letter" width="500" height="413" border="0" usemap="#letter" id="letter">
<map name="letter">
<area shape="rect" coords="153,129,209,157" href="#hard" onMouseOver="beating()">
<area shape="rect" coords="379,157,445,190" href="#love" onMouseOver="fallInLove()">
<area shape="rect" coords="379,195,447,226" href="#rose" onClick="sendRose()">
<area shape="rect" coords="132,324,209,356" href="#marry" onClick="willYouMarry()">
<area shape="rect" coords="381,8,495,94" href="#close" onClick="MM_showHideLayers('layerletter','','hide')">
</map>
</p>
</div>
......
-
In order to get access to Java FX application, we need to add id parameter to the application at deploy time. Modify the javascript code in HTML page to
deploy Java FX application as follows
<script src="http://dl.javafx.com/1.1/dtfx.js"></script>
<script>
javafx(
{
archive: "LoveLetter.jar",
draggable: true,
width: 600,
height: 400,
code: "loveletter.Letter",
name: "LoveLetter",
id: "MyApplet"
}
);
</script>
-
Modify the callback method beating() to access FX Node variable beating as follows.
function beating() {
//TODO: access beating variable of Java FX
var app = document.getElementById("MyApplet");
app.script.beating.play();
}
In JavaScript context, we can get instance of Java FX application by calling
document.getElementById("<App ID>");. Variables defined in Java FX
application can be access directly with <app instance>.script.<variable name>.
-
We can also call Java FX methods through the application instance. Complete the callback
methods as follows
function fallInLove() {
//TOOD: call fallInLove() method of Java FX
var app = document.getElementById("MyApplet");
app.script.fallInLove();
}
function sendRose() {
//TODO: call sendRose() method of Java FX
var app = document.getElementById("MyApplet");
app.script.sendRose();
}
function willYouMarry() {
//TODO: call willYouMarryMe() method of Java FX
var app = document.getElementById("MyApplet");
app.script.willYouMarryMe();
}
-
Open MyLoveLetter.html in a browser. Click the envelope icon to show the love letter. Try
to move the mouse over "HARD", "LOVE", and click on "ROSES", "MARRY", you will see Java FX
response the JavaScript events.
In this step, we're going to call JavaScript methods from Java FX code embedded in the web page.
-
Let's take a look at some javascript code in MyLoveLetter.html. There are two javascript methods:
sayYes(), sayNo() to update the content of web page without refreshing.
<script>
......
function sayYes() {
MM_showHideLayers('layerletter','','hide','layerletter-yes','','show','layerletter-no','','hide');
}
function sayNo() {
MM_showHideLayers('layerletter','','hide','layerletter-yes','','hide','layerletter-no','','show');
}
......
</script>
-
Double click Letter.fx in Netbeans to open it in the editor window. Method willYouMarryMe()
makes the hidden button group visible.
......
def yesButton: Node = SwingButton {
text: "Yes"
width: 70
action: function() {
accept();
}
}
def noButton: Node = SwingButton {
text: "No"
width: 70
action: function() {
reject();
}
}
def buttons: Node = HBox {
translateX: 70
translateY: 270
spacing: 10
content: [
yesButton, noButton
]
opacity: 0.0
disable: true
}
......
public function willYouMarryMe() {
buttons.disable = false;
fadeIn(buttons);
}
Once either button is clicked, callback method either accept() or reject() will be called. Besides
activate some Java FX animations, we'd like to change the DOM content of the host page by calling JavaScript
methods sayYes() or sayNo() perspectively.
-
In order to use LiveConnect APIs, we need to include java plugin framework to the libraries of our Java FX applicatioin.
Right click on LoveLetter project in Projects tag window, select Properties from the context menu.
-
Select Libraries from Categories, click button Add JAR/Folder. In the filechooser, browse to directory
<JRE_HOME>/lib directory, add plugin.jar.
-
LiveConnect API defines netscape.javascript.JSObject as the delegate of JavaScript object in
Java/Java FX code. So we need to add import to the code first. Add import as follows
import netscape.javascript.JSObject;
-
Modify accept() and reject() methods as follows to call javascript methods
function accept() {
buttons.disable = true;
fadeOut(buttons);
heartFly();
//TODO: call javascript method sayYes()
var window = JSObject.getWindow(FX.getArgument("javafx.applet") as java.applet.Applet);
window.eval("sayYes()");
}
function reject() {
buttons.disable = true;
fadeOut(buttons);
heartBroken();
//TODO: call javascript method sayNo()
var window = JSObject.getWindow(FX.getArgument("javafx.applet") as java.applet.Applet);
window.eval("sayNo()");
}
Java FX application deployed in the browser is compiled to an Applet. The instance of Applet can be
got by calling FX.getArgument("javafx.applet") method. Once we get the applet instance, the
interaction with JavaScript is exactly the same as what we have introduced in the perious steps.
-
Right click LoveLetter project in the Projects tag window of Netbeans, select Build Project from
the context menu to re-create the jar file. Copy LoveLetter.jar located in <lab_root>/javaseclient/execise/LoveLetter/dist
directory to <lab_root>/javaseclient/execise/page directory, replace the original one.
-
Open MyLoveLetter.html with the browser, click the Click the envelope icon to show the love letter. Click word MARRY
to show Yes and No buttons in Java FX. Click either button. Notice the content of the love letter is changed
without refreshing the page.
Summary
In this execise, we have leant how Java/Java FX code can access the javascript context of the web it's deployed to. As well,
the javascript code within the host page can also access Java/Java FX context via Liveconnect API.
With that interactibility, developers can create very rich web application mixed Java/Java FX and javascript.
Back to top
Next exercise
|