Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling GWT Java function from JavaScript

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

like image 903
frodo Avatar asked Apr 18 '13 10:04

frodo


People also ask

Can I call a Java function from JavaScript?

JavaScript cannot call java method directly since it is on the server. You need a Java framework like JSP to call when a request is received from JavaScript.

Can we call Java method from HTML?

The outcome of the scripts below is to have the HTML call the Java file, and have that Java file execute with the text that was extracted from the HTML text-boxes. I've made sure the API's (servlet, APEX) are correctly installed.

What is GWT jsni and how to use it?

GWT JSNI is used to solve problems such as, when we need to integrate GWT with existing handwritten JavaScript or with a third-party JavaScript library. Occasionally, we need to access low-level browser functionality which is not exposed by the GWT class API’s.

How to call a java function from JavaScript?

Before calling Java from JavaScript, we need to set up the JavaScript file itself. Create a new file with the name script.js in the src/main/webapp/frontend/ directory and code a simple function in it: We need to import this file in the Java class. Annotate the MainView class with @JavaScript as follows:

How do I call the greet function in JavaScript?

With the JavaScript file loaded, we can call the greet function in the constructor as follows: The getElement () method returns a Java representation of the <div> element in the DOM. There a small improvement we can make to this line of code. We can separate the argument values from the function call and get the same behavior:


2 Answers

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).

like image 52
Manolo Carrasco Moñino Avatar answered Oct 15 '22 08:10

Manolo Carrasco Moñino


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.

like image 41
jgleoj23 Avatar answered Oct 15 '22 08:10

jgleoj23