Calling GWT Java function from JavaScript

16,251

Solution 1

Let me explain a bit more about exporting GWT stuff to the JS world. You have several options to do that, but I will focus on three methods.

[EDITED]

0- JsInterop: GWT maintainers are working in a new feature to easily export java methods to javascript, and wrap javascript objects. The feature was very experimental in 2.7.0 lacking some features, but in 2.8.0 will be almost functional. Please take a look to the Design Document, and other discussions in the mailing list.

[END]

1- JSNI: The first one is to write your own jsni, in this case you have to be aware about the possible mistakes you could make. Basically these mistakes are because you have to know how to deal with types. In your case if you want to get a javascript array (like you are asking in your comment below), the solution could be:

public static native void exportMyFunction()/*-{
  $wnd.handleAnchorClick = @company.package.class.JSNITest::handleAnchorClick(*);
}-*/;

public static void handleAnchorClick(JsArrayMixed args) {
  Window.alert("Current row and Column is " +
                args.getNumber(0) + "  " + args.getNumber(1));
}

public void onModuleLoad() {
  exportMyFunction();
}

//javascript code
window.handleAnchorClick([1,2])

Note that JSNI only allows you to pass primitive types (except long) and JavaScriptObject objects. So when passing a javascript array, you have to receive it with a JavaScriptObject like in the example. In this case, since javascript only uses a type for numbers, args.getNumber will return always a double, and you have to convert in java.

2- gwt-exporter For exporting large projects, or when you need to handle complex objects and classes I'd rather use gwt-exporter

static class MyClass implements Exportable {
  @Export("$wnd.handleAnchorClick")
  public static void handleAnchorClick(double[] args) {
    Window.alert("Current row and Column is " +args[0] + "  " + args[1]);
  }
}

public void onModuleLoad() {
  GWT.create(MyClass.class);
}

//javascript code
window.handleAnchorClick([1,2])

gwt-exporter will deal with any kind of primitive types (even with long) myfunc(long[] args), with var-args myfunc(long...args), it supports method overload, and much more.

3- gwtquery Finally if you prefer gwtquery, you can use a technique to add function properties to any js object like window

// The GQuery Properties object is able to wrap a java Function object
// into an js property.
Properties wnd = window.cast();
wnd.setFunction("handleAnchorClick", new Function() {
  public void f() {
    // Get the js arguments[] array
    JsArrayMixed args = arguments(0);
    // Get the first element of the arguments[] array
    JsArrayMixed ary = args.getObject(0);

    Window.alert("Current row and Column is " +
                  ary.getNumber(0) + "  " + ary.getNumber(1));
  }
});

//javascript code
window.handleAnchorClick([1,2])

With gquery you can use the gwt JsArrayMixed class which always returns a number as a double, or you can use a JsCache which allows to convert numbers to any other numeric type in java ((JsCache)ary.get(1, Integer.class)

As a summary, I would rather use gwt-exporter as the first option because it is specialized in handling this problematic. As a second option, I would use gquery which is a serious complement to gwt. Finally, I would avoid to use hand-written jsni when possible, Javascript is normally a source of issues and mistakes (think that the main goal of gwt is not to deal with js).

Solution 2

You should consider GWT exporter. You might even consider waiting because GWT 2.8 should come out pretty soon. It was supposed to come out some time around The begging of 2015. 2015 has already begun and they're demonstrating at GWT.create right now so it should come out any day now. If you can't wait then you can either use experimental is interop, JSNI like the top answer says to or GWT exporter. JSNI is more complicated and involves a lot of boiler plate code so if you have to do a lot of js interop I recommend GWT-exporter.

Share:
16,251
frodo
Author by

frodo

Updated on June 12, 2022

Comments

  • frodo
    frodo almost 2 years

    I am a newcomer to GWT and JavaScript. There are similar question of this type I have tried to follow, but I keep failing.

    I have a GWT app, I need to call a Java function from Javascript( on the onclick of a href tag, in particular.) Following is what I have done.

    public class JSNITest {
    
     public static void handleAnchorClick(int a , int b) {
       Window.alert("Current row and Column is " + a + "  " + b);
     }
    
     public static native void exportMyFunction()/*-{
        $wnd.handleAnchorClick = function(param1,param2){
            @company.package.class.JSNITest::handleAnchorClick(*)(param1,param2);
     }-*/;
    
    }
    

    And in the HTML,

    <a href="javascript:handleAnchorClick(a1,a2);">link</a> 
    

    (a1 , a2) are two integer variables in my code. I have also called EnclosingClass.exportMyFunction() in the entry point function. I keep running into various kinds of exceptions(No Such class exception). Can someone please correct me?

    Regards

  • frodo
    frodo about 11 years
    Hmm. Just found out what was wrong. I was giving the path to the function incorrectly. :D. Damn.
  • frodo
    frodo about 11 years
    I just wanted to ask you, is it possible for me to pass java arrays to the javascript function when I am making the call? If yes, how?
  • Manolo Carrasco Moñino
    Manolo Carrasco Moñino about 11 years
    edited my answer to explain how to handle it with different options
  • frodo
    frodo about 11 years
    Thanks a lot for your time. Its a great answer, much more information than I could get by browsing on the net :P ! I have a final query, say I wanted to send in a int[] vars , would the syntax be any different? In your example u have used [1,2].
  • Manolo Carrasco Moñino
    Manolo Carrasco Moñino about 11 years
    You only can send numbers, because in js you only have numbers. Depending on the solution you select you have to do the conversion by hand or not. Edited my answer.
  • PaintedRed
    PaintedRed almost 9 years
    Do you have working example with gwt-exporter? See my question stackoverflow.com/questions/30990652/…
  • PaintedRed
    PaintedRed almost 9 years
    Can you help me a little with my question: stackoverflow.com/questions/30990652/…