Search code examples
javajavascriptgwtjsniexporter

Possibility to call nonstatic gwt java method from javascript


General Aim: call some nonstatic java method from javascript

Description: To find gwt's widget on DOM in Java Applet code and call it's java method(non static)


JSObject win = JSObject.getWindow(this);
JSObject doc = (JSObject) win.getMember("document");
JSObject gwtWidget = (JSObject) doc.call("getElementsByName", widgetName);

//todo: have possibility to call `exported` java method over here, smth like:
//Object[] params = new Object[1];
//params[0] = widgetName;
//Object result = gwtWidget.call("exportedJavaMethod", params);

//todo: or just call global ($wnd) static JSNI bridge method:
//Object result = win.call("exportedJavaMethod", params);
//

The problem is: I can find by widget's id not the widget, but it's DivElement which does not have any exported instanced methods.

My widget class is Exportable (gwt-export):


@Export(value="somewidget")
public class SomeWidget extends SimplePanel implements ..., Exportable {
    private final String id = "id_some_widget_" + count++;
    private static int count = 0;

    public SomeWidget () {
        getElement().setAttribute("name", id);
        getElement().setId(id);
    }
    ...

    public static Element getInstanceById(String elementId) {
        Element someWidget= DOM.getElementById(elementId);
        return someWidget;
    }

    public String getSomeInstancedData() {
        return "useful_inner_data" + this.id;
    }

So, for example I'd like to find the concrete widget added to DOM and call nonstatic method getSomeInstancedData() in javascript. Is it possible at all?

Suppose smth like:


var someWidget = document.getElementById(widgetId);
alert(someWidget.getSomeInstancedData());

//or:
var someWidgetExported = com.mypackage.widgets.somewidget.getInstanceById(listenerId);
alert(someWidgetExported.getSomeInstancedData());

In Base module I write:


ExporterUtil.exportAll();

There is a View(ViewWithSomeWidget.ui.xml) that contains this widget:

...
base:Form
base:SomeWidget ui:field="someWidget" ...
...
/base:SomeWidget
...

When SomeWidget does not implement Exportable, project runs well, but I couldn't call nonstatic methods of found widget's DIV element.

By the time, to solve the problem SomeWidget implements Exportable, but progect doesn't show View with the SomeWidget well because of ClassCastException using deferred binding:


ClassCastException: com.mypackage.widgets.SomeWidgetExporterImpl cannot be cast to com.mypackage.widgets.SomeWidget

So, probably there are any other methods to find widget's javascript object and call it's exported java method? In any ways, any idea is much appreciated.


Solution

  • You can declare a javascript function, which will fire the non-static method.

    For example:

    package com.example;
    public class Layout extends VLayout() {
        private String nonStaticVar = "nonStaticVar";
        public Layout() {
            declareMethod(this);
        }
    
        //Method which declares non-static method in javascript
        public native void declareMethod(Layout layout) /*-{
            var layout = layout;
            $wnd.doSomething = function(someString) {
                [email protected]::doSomething(Ljava/lang/String;)(someString);
            }
        }-*/;
    
        //Non static method which is being called
        public String doSomething(String someString) {
            //Do something, e.g. set var in this instantiated class, or output stuff
            this.nonStaticVar = someString;
            Window.alert(someString);
        }
    }
    

    Now, calling doSomething("bla"); from javascript will call your non-static method.