GWT: ¿Se puede llamar al método Java desde JavaScript externo en lugar de JSNI?

I'm trying to move most of my native JavaScript code out of JSNI methods and into scripts, and just leveraging the native JSNI methods to call those external methods.

Right now I'm having difficulties with one of my click handlers. When the user clicks a particular element, a JSNI method does some JQuery-based animation, and then calls a Java method in the callback. A simple example is this:

public native void attachClickHandler(SomeCustomPanel customPanel) /*-{
    $wnd.jQuery("#theElement").click(function() {
        // some JQuery animation logic here...
        $wnd.jQuery("#theElement").animate({ top: "500px" }, 500, function() {
            customPanel.@com.something.whatever.client.SomeCustomPanel::doSomething()();
        });
        // some other code here...
    });
}-*/;

This code works. It compiles and works as expected. I want to move this into an external JavaScript. I tried the following. I put this in the external JavaScript:

function attachClickAction(customPanel) {
    $("#theElement").click(function() {
        // other stuff...
        $("#theElement").animate({ top: "500px" }, 500, function() {
            customPanel.@com.something.whatever.client.SomeCustomPanel::doSomething()();
        });
        // other stuff...
    });
}

And modified the native function like this:

public native void attachClickHandler(SomeCustomPanel customPanel) /*-{
    $wnd.attachClickAction(customPanel);
}-*/;

But is incorrect. The JavaScript file won't even load because this is not correct JavaScript. (Chome's dev tools give me the error message "Uncaught SyntaxError: Unexpected identifier".)

Is there a way to call a Java method from an external JavaScript file, no from a JSNI method?

I'm in GWT 2.4, if it matters.

preguntado el 24 de agosto de 12 a las 22:08

3 Respuestas

La respuesta es no, you cannot call Java methods explicitly from the external JavaScript function.

However, you can be clever and take advantage of the fact that JavaScript allows you to pass functions themselves as parameters.

I modified my JavaScript function like so:

function attachClickAction(callbackFunction) {
    $("#theElement").click(function() {
        // other stuff...
        $("#theElement").animate({ top: "500px" }, 500, callbackFunction);
    // other stuff...
    });
}

And in my Java code I explicitly passed the Java method as a callback function parameter:

public native void attachClickHandler(SomeCustomPanel customPanel) /*-{
    $wnd.attachClickAction(function() {
        customPanel.@com.something.whatever.client.SomeCustomPanel::doSomething()();
    });
}-*/;

This way, when the JSNI method compiles, it correctly calls the doSomething() Java method, and that method call is correctly passed in its entirety to the external JavaScript function.

Respondido 24 ago 12, 23:08

Note: you should surround the call to customPanel...doSomething()() con $entry(). - Keldon Alleyne

@avasopht -- Why? I've never seen that construct before. Can you explain? - Roddy de los guisantes congelados

It wraps the call around some try/catch statements so that no Java code exceptions from GWT/javascript will reach the pure javascript code space. - Keldon Alleyne

Although you cannot make calls to Java classe's methods directly from JavaScript with vanilla GWT, exportador de gwt does a lot of the plumbing required for calling the methods of 'Java' objects from native JavaScript.

Puedes hacer cosas como:

Java:

@ExportPackage("")
@Export("MYOBJ");
class MyClass implements Exportable {
   public void doSomething();
}

JavaScript:

MYOBJ.doSomething();

gwt-exporter works well with GWT 2.4,

Respondido el 19 de Septiembre de 12 a las 01:09

I can't add external dependencies, unfortunately, but that you for the suggestion. - Roddy de los guisantes congelados

Yes, you can export your Java (GWT) methods as JavaScript functions, and you can put your Java objects into JavaScript variables. Here's a simple example:

@Override
public void onModuleLoad() {
  exportJavaMethodsToJs();

  final SomeCustomPanel firstCustomPanel = new SomeCustomPanel("first");
  exportJavaObjectToJs("firstCustomPanel", firstCustomPanel);

  final SomeCustomPanel anotherCustomPanel = new SomeCustomPanel("another");
  exportJavaObjectToJs("anotherCustomPanel", anotherCustomPanel);
}

native void exportJavaMethodsToJs() /*-{
  $wnd.doSomething = function(panel) {
    panel.@com.something.whatever.client.SomeCustomPanel::doSomething()();
  }
  // Export any methods you need in JavaScript here...
}-*/;

native void exportJavaObjectToJs(final String key, final Object object) /*-{
  $wnd[key] = object;
}-*/;

Then, in JavaScript (after onModuleLoad() has been called!), you can use it easily like

doSomething(firstCustomPanel);
doSomething(anotherCustomPanel);

Your example would now look like this:

jQuery("#theElement").click(function() {
    // some JQuery animation logic here...
    $wnd.jQuery("#theElement").animate({ top: "500px" }, 500, function() {
        doSomething(firstCustomPanel);
    });
    // some other code here...
});

Respondido el 30 de diciembre de 12 a las 01:12

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.