MigrateFromGWT

From APIDesign

(Difference between revisions)
Jump to: navigation, search
(Convert to Annotations)
Line 51: Line 51:
=== Convert to Annotations ===
=== Convert to Annotations ===
-
The first step is to convert comments into something that [[JVM]] can consume. Since [[JDK]]5 the proper way of attaching additional information to methods is to use [[annotations]]. Let's us use ''@JavaScriptBody'' as provided by [[netbeans:Html4Java|HTML4J]] library: see [http://deadlock.netbeans.org/job/html+java/lastSuccessfulBuild/artifact/boot/target/site/apidocs/index.html javadoc].
+
The first step is to convert comments into something that [[JVM]] can consume. Since [[JDK]]5 the proper way of attaching additional information to methods is to use [[annotations]]. Let's us rewrite the code to use ''@JavaScriptBody'' as provided by [[netbeans:Html4Java|HTML4J]] library (see its [http://deadlock.netbeans.org/job/html+java/lastSuccessfulBuild/artifact/boot/target/site/apidocs/index.html javadoc]). The goal is to have source like this:
 +
 
 +
<source lang="java">
 +
public class ButtonApp implements Runnable {
 +
 +
public static void onLoad() {
 +
alert("Initializing...");
 +
html("<button id='x'>Click me!</button>");
 +
onClick("x", new Runnable() {
 +
public void run() {
 +
alert("Button was clicked!");
 +
later(new ButtonApp(), 1000);
 +
}
 +
});
 +
}
 +
 +
public void run() {
 +
alert("One second after that!");
 +
}
 +
 +
@net.java.html.js.JavaScriptBody(args = {"r", "time"}, javacall = true, body =
 +
" window.setTimeout(function() {\n" +
 +
" r.@java.lang.Runnable::run()();\n" +
 +
" }, time);\n" +
 +
" ")
 +
public static native void later(Runnable r, int time);
 +
 +
@net.java.html.js.JavaScriptBody(args = {"html"}, body =
 +
" var b = document.getElementsByTagName(\"body\")[0];\n" +
 +
" b.innerHTML = html;\n" +
 +
" ")
 +
public static native void html(String html);
 +
 
 +
@net.java.html.js.JavaScriptBody(args = {"msg"}, body =
 +
" alert(msg);\n" +
 +
" ")
 +
public static native void alert(String msg);
 +
 
 +
@net.java.html.js.JavaScriptBody(args = {"id", "r"}, javacall = true, body =
 +
" document.getElementById(id).onclick = function() {\n" +
 +
" r.@java.lang.Runnable::run()();\n" +
 +
" };\n" +
 +
" ")
 +
public static native void onClick(String id, Runnable r);
 +
 
 +
}
 +
</source>
 +
 
 +
To help us with migration there is a [[NetBeans]] module that can do this for us automatically.

Revision as of 18:11, 29 January 2014

GWT has a lot of drawbacks which Bck2Brwsr project addresses by allowing us to use real JVM. As such there is a value in migrating to this new system. Moreover the migration is quite easy. Let me give you a demo.

GWT Project

The primary focus right now is to show that the GWT Java to JavaScript native interface methods can easily be migrated to real HotSpot virtual machine. Imagine following application that talks directly to JavaScript in the browser:

public class ButtonApp implements Runnable {
 
   public static void onLoad() {
        alert("Initializing...");
        html("<button id='x'>Click me!</button>");
        onClick("x", new Runnable() {
            public void run() {
                alert("Button was clicked!");
                later(new ButtonApp(), 1000);
            }
        });
    }
 
    public void run() {
        alert("One second after that!");
    }
 
  public static native void later(Runnable r, int time) /*-{
        window.setTimeout(function() {
            r.@java.lang.Runnable::run()();
        }, time);
    }-*/;
 
    public static native void html(String html) /*-{
        var b = document.getElementsByTagName("body")[0];
        b.innerHTML = html;
    }-*/;
 
    public static native void alert(String msg) /*-{
       alert(msg);
    }-*/;
 
    public static native void onClick(String id, Runnable r) /*-{
       document.getElementById(id).onclick = function() {
        r.@java.lang.Runnable::run()();
       };
    }-*/;
 
}

Of course, this is not typical GWT application. It does not use GWT widgets library. However the point to demonstrate is different: we want to see if we can convert the low level JSNI comments into something that can run on top of real JDK. Because if we can, reimplementing the widgets or other libraries is then just a bit of work.

Convert to Annotations

The first step is to convert comments into something that JVM can consume. Since JDK5 the proper way of attaching additional information to methods is to use annotations. Let's us rewrite the code to use @JavaScriptBody as provided by HTML4J library (see its javadoc). The goal is to have source like this:

public class ButtonApp implements Runnable {                                                                                                                                                     
 
    public static void onLoad() {                                                                                                                                                            
        alert("Initializing...");                                                                                                                                                                
        html("<button id='x'>Click me!</button>");                                                                                                                                               
        onClick("x", new Runnable() {                                                                                                                                                            
            public void run() {                                                                                                                                                                  
                alert("Button was clicked!");                                                                                                                                                    
                later(new ButtonApp(), 1000);                                                                                                                                                    
            }                                                                                                                                                                                    
        });                                                                                                                                                                                      
    }                                                                                                                                                                                        
 
    public void run() {                                                                                                                                                                          
        alert("One second after that!");                                                                                                                                                         
    }                                                                                                                                                                                            
 
    @net.java.html.js.JavaScriptBody(args = {"r", "time"}, javacall = true, body = 
        "        window.setTimeout(function() {\n" +                                                                                                                                             
        "            r.@java.lang.Runnable::run()();\n" + 
        "        }, time);\n" + 
        "    ")
    public static native void later(Runnable r, int time);
 
    @net.java.html.js.JavaScriptBody(args = {"html"}, body =
        "        var b = document.getElementsByTagName(\"body\")[0];\n" + 
        "        b.innerHTML = html;\n" + 
        "    ")
    public static native void html(String html);
 
    @net.java.html.js.JavaScriptBody(args = {"msg"}, body =
        "       alert(msg);\n" + 
        "    ")
    public static native void alert(String msg);
 
    @net.java.html.js.JavaScriptBody(args = {"id", "r"}, javacall = true, body =        
        "       document.getElementById(id).onclick = function() {\n" + 
        "        r.@java.lang.Runnable::run()();\n" + 
        "       };\n" + 
        "    ")
    public static native void onClick(String id, Runnable r);
 
}

To help us with migration there is a NetBeans module that can do this for us automatically.

Personal tools
buy