Forum Controls
Spotlight Features

The Rich Engineering Heritage Behind Dependency Injection

Andrew McVeigh takes us on a tour of the rich heritage behind dependency injection, what it represents, and tells us why its here to stay.

NetBeans 6: Matisse Updates

NetBeans 6 delivers great updates to the Matisse GUI builder. Spend a few minutes with Roman Strobl and get an expert briefing on what's new and what has changed.

Introduction to Groovy Part 3

In this, the third and final installation of Andres' Introduction to Groovy series, you learn about how Groovy handles variable numbers of arguments, named parameters, currying, and more about Groovy operators. Including, some new operators.

Easier Custom Components with Swing Fuse

Swing Fuse (actually just Fuse), is a framework designed to make it easier to create your own custom desktop components. In this article, Daniel Spiewak shows you how to get started and provides sample source code you can download.

Benchmark Analysis: Guice vs Spring

Willam Louth shows how he uses JXInsight Probes to investigate probable performance issues with code bases that he is not familiar with. He also highlights possible pitfalls in creating a benchmark, as well as in the analysis of results.
Replies: 1 - Pages: 1  
Threads: [ Previous | Next ]
  Click to reply to this thread Reply

Scripting: Javascript to Java Integration (Part 1)

At 3:47 PM on Dec 30, 2006, R.J. Lorimer wrote:

Recently, I discussed how you can compile Javascript written for the Java 6 scripting engine to make it a faster, pre-parsed script . In this tip I'd like to extend that base knowledge by discussing how you can interact with Java code with the Rhino Javascript engine.

One of the nicest features of Rhino is it's ability to call back into Java anytime you want. As an example, I'll reproduce one of the many SWT snippets (Snippet 223).

Before reading this, you should familiarize yourself with the source code of Snippet 223 , which creates an SWT ExpandBar, and a series of ExpandItems.

To start implementing Snippet 223 in Javascript, you have to choose what part of your code you want to implement in Java, and what part you want implemented in Javascript. I'm going to leave the construction of the display and shell as part of the Java code, and simply make the setup of the expand bars the responsibility of the script. The choise of this 'line' is really dependent on your circumstances; my choice in this case is largely arbitrary. First, let's implement the Java driver required to setup the SWT shell, and run the script:

public static void main(String[] args) throws Exception {
	Display display = new Display ();
	Shell shell = new Shell (display);
		
	ScriptEngineManager manager = new ScriptEngineManager();
	ScriptEngine engine = manager.getEngineByName("js");
	Bindings bindings = engine.createBindings();
	bindings.put("display", display);
	bindings.put("shell", shell);
	Reader r = new BufferedReader(new InputStreamReader(Test.class.getResourceAsStream("test.js")));
	try {
		engine.eval(r, bindings);
	}
	finally {
		r.close();
	}
	
	shell.open();
	while (!shell.isDisposed ()) {
		if (!display.readAndDispatch ()) {
			display.sleep ();
		}
	}
	display.dispose();
}

Basically, we create the SWT display and shell, throw them in to the bindings for the script, and then execute the script. In this case we expect the script to be in a 'test.js' file in the same directory as this Java class. Note that I'm not compiling the script as I discussed in the prior article because once the script has been run, we will never be running it again.

So now we need to implement test.js . There are multiple ways to do this - in this case I'm going to implement it using a very similar implementation to the Java snippet itself, but I'm going to use a few simple JS features along the way.

First, we need to import the Java packages required to run the setup code:

importPackage(org.eclipse.swt);
importPackage(org.eclipse.swt.widgets);
importPackage(org.eclipse.swt.layout);
importPackage(org.eclipse.swt.graphics);

importPackage(...) is a built-in function of Rhino that allows you to gain access to Java classes in a particular package.

Once you have classes imported, it's just a matter of writing code. For the most part, Rhino JS code can look a lot like Java:

shell.setLayout(new FillLayout());
shell.setText("ExpandBar Example");

Remember, however, that Javascript doesn't have explicit type definitions, so you don't need to declare variable types; here is another block of code that shows that:

bar = new ExpandBar (shell, SWT.V_SCROLL);		
// First item
composite = new Composite (bar, SWT.NONE);
layout = new GridLayout ();
layout.marginLeft = layout.marginTop = layout.marginRight = layout.marginBottom = 10;
layout.verticalSpacing = 10;

When working with Javascript, it's easy to forget that you're not in Kansas anymore. While Javascript looks a lot like Java, it is advantageous to keep in mind that it is a very different language. For one thing, in this short example I can declare a few functions when necessary to help simplify redundant tasks. Here is a block of code from the snippet which feels fairly redundant:

Button button = new Button (composite, SWT.PUSH);
button.setText("SWT.PUSH");
button = new Button (composite, SWT.RADIO);
button.setText("SWT.RADIO");
button = new Button (composite, SWT.CHECK);
button.setText("SWT.CHECK");
button = new Button (composite, SWT.TOGGLE);
button.setText("SWT.TOGGLE");

Since the original example of Java code had the text of the button matching the button type exactly, it makes sense to take advantage of the Javascript 'eval' function:

function newButton(type) {
	obj = new Button(composite, eval(type));
	obj.setText(type);
	return obj;
}
newButton("SWT.PUSH");
newButton("SWT.RADIO");
newButton("SWT.CHECK");
newButton("SWT.TOGGLE");

In this section of code I've declared a function 'newButton' which simply takes a string representing the button type. By using 'eval', we can invoke that string as Javascript code, thereby computing the value. We can easily take the result of this function and make furthor modifications if we want:

button = newButton("SWT.TOGGLE");
button.setText("This is a toggle");

I should clarify that I'm not picking on the Java implementation from Eclipse.org; SWT snippets are purposefully done without any intermediate helper methods to keep all of the code being used in a easy to consume top-to-bottom read, I'm simply showing how Javascript can also easily evolve into something better. Also, this is only a tiny slice of how Javascript can interact with your Java libraries, and in general change the way you code. I didn't get in to object-oriented Javascript with prototypes, higher-order functional programming, or any of the other unique Javascript features, but rest assured they all work quite well.

In the next tip I will discuss some of the more advanced situations when integrating with Java as well as pitfalls and shortcomings you may run in to.

Here is the full test.js file representing snippet 223:

importPackage(org.eclipse.swt);
importPackage(org.eclipse.swt.widgets);
importPackage(org.eclipse.swt.layout);
importPackage(org.eclipse.swt.graphics);
 
function newButton(type) {
	obj = new Button(composite, eval(type));
	obj.setText(type);
	return obj;
}
 
function newLabel(img, text) {
	obj = new Label(composite, SWT.NONE);
	if(img != null) obj.setImage(img);
	if(text != null) obj.setText(text);
	obj;
}
 
function newItem(num, text) {
	obj = new ExpandItem (bar, SWT.NONE, num);
	obj.setText(text);
	obj.setHeight(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
	obj.setControl(composite);
	return obj;
}
 
shell.setLayout(new FillLayout());
shell.setText("ExpandBar Example");
 
bar = new ExpandBar (shell, SWT.V_SCROLL);		
// First item
composite = new Composite (bar, SWT.NONE);
layout = new GridLayout ();
layout.marginLeft = layout.marginTop = layout.marginRight = layout.marginBottom = 10;
layout.verticalSpacing = 10;
composite.setLayout(layout);
 
newButton("SWT.PUSH");
newButton("SWT.RADIO");
newButton("SWT.CHECK");
button = newButton("SWT.TOGGLE");
button.setText("This is a toggle");
newItem(0, "What is your favorite button");
	
// Second item
composite = new Composite (bar, SWT.NONE);
layout = new GridLayout (2, false);
layout.marginLeft = layout.marginTop = layout.marginRight = layout.marginBottom = 10;
layout.verticalSpacing = 10;
composite.setLayout(layout);
 
newLabel(display.getSystemImage(SWT.ICON_ERROR), null);
newLabel(null, "SWT.ICON_ERROR");
newLabel(display.getSystemImage(SWT.ICON_INFORMATION), null);
newLabel(null, "SWT.ICON_INFORMATION");
newLabel(display.getSystemImage(SWT.ICON_WARNING), null);
newLabel(null, "SWT.ICON_WARNING");
newLabel(display.getSystemImage(SWT.ICON_QUESTION), null);
newLabel(null, "SWT.ICON_QUESTION");
newItem(1, "What is your favorite icon").setExpanded(true);
		
// Third item
composite = new Composite (bar, SWT.NONE);
layout = new GridLayout (2, true);
layout.marginLeft = layout.marginTop = layout.marginRight = layout.marginBottom = 10;
layout.verticalSpacing = 10;
composite.setLayout(layout);
newLabel(null, "Scale");
new Scale (composite, SWT.NONE);
newLabel(null, "Spinner");	
new Spinner (composite, SWT.BORDER);
newLabel(null, "Slider");	
new Slider (composite, SWT.NONE);
newItem(2, "What is your favorite range widget");
 
bar.setSpacing(8);
 
shell.setSize(400, 350);

1 . At 6:17 AM on Mar 19, 2007, Israr Ahmed wrote:
  Click to reply to this thread Reply

Re: Scripting: Javascript to Java Integration (Part 1)

That was nice article and helped me a lot in my project.
There certainly have been performance issues with Java. We've been working really hard on them. The primary way we've attacked the problem is with advanced virtual machines. The performance has been getting very nice. --James Gosling, 1999.

thread.rss_message