Using JSNI in GWT

The JavaScript Native Interface (JSNI) in the Google Web Toolkit (GWT) allows you to use parts of the GWT application outside of the app, and also to use JavaScript that it not part of the GWT app. This tutorial will show you how to read in JavaScript variables set on the page, and how to call GWT functions from the html page.

Getting an external variable

Instead of making an RPC call to get a variable needed by the GWT application on the page it is possible to set a JavaScript variable to the needed data either statically or dynamically while the page is being generated with PHP or another server side language. This variable is then grabbed by a JSNI function and usable by GWT. The variable is set like normal in the HTML or in an external JavaScript file like this:

var first_name = “Frank”;

A native function can then pull grab this variable from within the GWT Java code.

public native String getFirstName()/*-{

return $wnd.first_name;

}-*/;

The native function is commented out in the Java code since it is JavaScript and not Java, but is called like a normal function in the rest of the code. $win represents the JavaScript Window object which is used here to reference our first_name variable on the page. The function will return the value of the first_name variable, and it can then be used in the GWT Java code like any other variable.

Calling a GWT function externally

Many times it is easier to call a normal JavaScript function to open a GWT popup or cause some other kind of result then it is to have GWT add buttons to the page to do this. This can be difficult since GWT will obfuscate the code and change the name of the functions making it very hard to call them externally. The solution is to use JSNI to create a JavaScript function inside of GWT with a name that will not change, and then have that function call the internal function whose name could be anything after compiling.

From inside GWT a JavaScript function can be created on the Window object which can then be called anywhere in the HTML page.

public class BlueApp implements EntryPoint {

public void onModuleLoad() {

setShowTrigger(this);

}

public void runApp() {

Window.alert(’I am a GWT function’);

}

public native void setShowTrigger(BlueApp x)/*-{

$wnd.showBlueApp = function () {

x.@com.company.client.BlueApp::runApp()();

};

}-*/;

}

When this module is loaded it creates a JavaScript function called showBlueApp(), and nothing else. This function can then be called from the HTML page and it will execute the runApp() GWT function. The runApp function is referenced in the JavaScript with its full path which includes the module name. The variable x is the class itself and is passed in using “this”. Once it is called the JavaScript alert will appear.
The showBlueApp function would then be called like any other JavaScript function from the HTML.

onclick="showBlueApp()"

17 Responses to “Using JSNI in GWT”

  1. islam_nassef says:

    thank you very much.
    this post helped me alot.

  2. Jean Vence says:

    Great article! Thanks. Now is there a way to call a normal javascript function from GWT? Also is it possible to share data amongst GWT and Javascript.

  3. lucius says:

    Yes there is. Just write a JSNI function in GWT and have it call the external JS function like it is a member of $wnd. Both functions and variables can be referenced with that.

  4. cklaure says:

    A moment you talk about php files and I don’t understand how use it.
    How can I do to call a php function ???
    Thanks

  5. Jason says:

    Great article! I am starting to use GWT now. It helps me a lot.
    One thing is I tried to use the above way to call GWT’s function externally.
    I have a button, once click it, it will call the GWT’s function.
    In IE browser, it works.
    In Firefox browser, it only works once, I means when the page is loaded,
    I click the call GWT function button, it only calls the GWT’s function only
    at the first time I click it, then it won’t call the function. I set the Firefox
    cache 0 mb. the Firefox version is 2.0.0.4. I don’t know how to solve it.

  6. lucius says:

    cklaure: You can’t call a PHP function directly from GWT. PHP is server side, so you need to do an RPC to call php page with your parameters in the query string and have the PHP page display the data you want. GWT will then pull in that page. You can have it output it in JSON, text, or XML form, whichever works best for you.

  7. Andrey says:

    Thanks! Really helps me to made a call from JS to Java. Great!

  8. Neil says:

    Great stuff – been struggling with getting an applet talking to a GWT app, this did the trick perfectly. Nice, simple example.
    Thanks.

  9. Ashish says:

    Hi,
    I used this code but I is not showing the alert message given in the runApp() and it is also not showing the error.

    I want to call a javascript method which is defined in another.js file.
    How can I use that method in my GWT client.
    Please help me.

  10. Rey Estanislao says:

    Thanks! It helps me a lot. Now I can call functions from js to java and vice versa. Your the man! Great article…

  11. Pedz says:

    Great article, very clear. It will help a lot of people like me, thank you.

  12. John says:

    Great article!

    A couple of points:
    1. You must pass a reference to the current class you can NOT do the following:
    this.@com.company.client.BlueApp::runApp()();

    2. If you want parameters in your function, add them in the “function()” declaration:

    $wnd.showBlueApp = function (someInt) {
    x.@com.company.client.BlueApp::runApp(I)(someInt);
    };

  13. Guy says:

    Simple and clear article that solved a problem that I was having for days now.

    I was trying to get the event from the YouTube player into GWT to discover when the video had ended, and couldn’t find such a simple solution.

    Thanks.

  14. Paul says:

    A good article but it should be stressed using jsni is supposed to only be used VERY sparingly. Use RPC calls whereever possible.

    Also try not to use static class/method modifiers – use the lazy form.

    Reason being:

    The GWT compiler optimises best when left alone to prune and work out where static (i.e non polymorphic/reflection using code) so it can optimise fully – JSNI routines are static and outside the scope of the compiler aswell…

  15. mac says:

    Can I retrive variable like this:

    var arr = [{"id":1,"name":"mac"},{"id":2,"name":"mac2"}];

    into GWT? What type must be retrieved by function?

  16. m2je says:

    very nice!!!!

  17. MiST says:

    Great, now I can finally make GWT handle the post-auth methods. Sweet. I love it!

Leave a Reply