Sep 22, 2009

GWT: JSNI (Javascript Native Interface)

why JSNI ?

Calling JavaScript from Java
– Format of methods
– The $wnd variable
– Argument types
Calling Java from JavaScript
– Format of method types
– Designating overloaded methods
– Argument types

IDEA
  • Write Java methods that call JavaScript
    – Enclose JavaScript code in comments
    •Use $wnd variable to access window object
    •Use $doc variable to access document object
    – Pass primitives, strings, and arrays only
  • JavaScript code can call Java
    – Use JNI-like format to refer to methods and fields
  • Notes
    – JSNI can be used only for pure client-side code
    • Method bodies ignored when used in server-side classes
    – JSNI should be used sparingly
    • Most normal JavaScript functionality available in GWT
    • Mostly used to wrap external JavaScript libraries
Basic Syntax
  • Declare method native
    – Can be private or public, static or instance
  • Use special comments for method body
    – Start method with /*-{
    – End method with }-*/;
    • private native void foo(...) /*-{ JavaScript-Code }-*/;
  • Argument and return types
    – String, numeric primitive, boolean
    • Treated normally as argument or return type
    – Array
    • Argument: only used to be passed back to Java
    • Return: only if array came from Java code
    – Object
    • Argument: special syntax for accessing (see later slide)
    • Return: only if Object came from Java code
    – JavaScriptObject
    • Argument: only if JavaScriptObject came from JavaScript code
    • Return: can only be used to pass to another JSNI method
  • Basic Syntax: Example (Core Code Adapted from Events Lecture)

public class GwtJsniApp implements EntryPoint {
private TextBox textfield;
private HTML resultArea;
public void onModuleLoad() {
textfield = new TextBox();
textfield.addKeyboardListener(new WowListener());
resultArea = new HTML("<i>Result will go here</i>");
RootPanel.get("textfieldID").add(textfield);
RootPanel.get("resultID").add(resultArea);
}

private class WowListener extends KeyboardListenerAdapter {
public void onKeyUp(Widget sender, char keyCode,
int modifiers) {
String text = textfield.getText();
resultArea.setHTML(text);
if(text.equalsIgnoreCase("test1")) {
alert1(text);
} else if(text.equalsIgnoreCase("test2")) {
highlight1("resultID");
} else if(text.equalsIgnoreCase("test3")) {
highlight2("resultID", text);
}
}
}

private native void alert1(String message) /*-{
$wnd.alert(message);
}-*/;

  • Using External JavaScript Libraries
    • Load the library
    – Put <script> tag in head of HTML page, or
    – Put <script> tag in AppName.gwt.xml file
  • Define JSNI method
    – As shown previously
  • Access objects and functions via $wnd
    – $wnd.someFunction(args)
    – new $wnd.SomeObject(args)
    – var $wnd.newFunction = function(args) { body }
  • Access document via $doc
    – $doc.title = "New Title";
Example: Using Scriptaculous:

HTML
<HTML>
<head><title>JSNI</title>
<link rel="stylesheet" href="./css/styles.css" type="text/css"/>
<!------ scripts folder installed in src/mainPackage/public
(Same place you put images and css files) --->
<script src="./scripts/prototype.js" type="text/javascript"></script>
<script src="./scripts/scriptaculous/scriptaculous.js?
load=effects" type="text/javascript"></script>
<script language='javascript' src='coreservlets.GwtJsniApp.nocache.js'>
</script>
</head>

JAVA

private class WowListener extends KeyboardListenerAdapter {
public void onKeyUp(Widget sender, char keyCode,
int modifiers) {
String text = textfield.getText();
resultArea.setHTML(text);
if(text.equalsIgnoreCase("test1")) {
alert1(text);
} else if(text.equalsIgnoreCase("test2")) {
highlight1("resultID");
} else if(text.equalsIgnoreCase("test3")) {
highlight2("resultID", text);
}
}
}
private native void highlight1(String id) /*-{
new $wnd.Effect.Highlight(id);
new $wnd.Effect.Shake(id);
}-*/;

WEB MODE
Calling Java from JavaScript
  • Follows Java Native Interface (JNI) format
    – Summary here. Details: see JNI reference or GWT docs.
  • Format for static methods
    – @className::methodName(paramSignature)(args)
    • className: fully qualified name
    • methodName: normal name
    • paramSignature: JNI parameter signature (see next page)
    • args: argument names
  • Format for instance methods
    – this.@className::methodName(paramSignature)(args)
    – obj.@className::methodName(paramSignature)(args)
    • obj must be passed in from Java
  • Format for field access
    – obj.@className::fieldName
Parameter Signatures
  • Separated by semicolons, not commas
  • Special format for types (copied from JNI)
  • Example
    – Real method (class is test.client.SomeClass)
    • public double foo(double d, String s) { ...}
    – JSNI call
    • var value =
    this.@test.client.SomeClass::foo(D; Ljava/lang/String)(2.5, "hi");

private class WowListener extends KeyboardListenerAdapter {
public void onKeyUp(Widget sender, char keyCode,
int modifiers) {
String text = textfield.getText();
resultArea.setHTML(text);
if(text.equalsIgnoreCase("test1")) {
alert1(text);
} else if(text.equalsIgnoreCase("test2")) {
highlight1("resultID");
} else if(text.equalsIgnoreCase("test3")) {
highlight2("resultID", text);
}
}
}
private double randomTime(double n){
return(Math.random() * n);
}
private void alert2(String text) {
Window.alert("Value: " + text);
}
private native void highlight2(String id, String text) /*-{
var time =
this.@coreservlets.client.GwtJsniApp::randomTime(D)(10);
this.@coreservlets.client.GwtJsniApp::alert2
(Ljava/lang/String;)(text);
new $wnd.Effect.Highlight(id, { duration: time});
new $wnd.Effect.Shake(id, { duration: time});
}-*/;
Result
Summary
  • Approach
    – Declare native
    – Enclose body in /*-{ ... }-*/;
    – Use $wnd to access window object
    – Use JNI format to call Java from JavaScript
  • Example
    private native void alert1(String message) /*-{
    $wnd.alert(message);
    }-*/;
  • Purpose
    – Mostly for wrapping existing JavaScript libraries
    – Most standard tasks can be done directly in GWT

0 comments:

Text Widget

Copyright © Vinay's Blog | Powered by Blogger

Design by | Blogger Theme by