The next and hopefully last release candidate for GWT 1.5 is almost upon us. In anticipation, we'd like to really crank up the excitement level and, well, the sheer geek factor of this here blog.
If you are new to GWT, you may be wondering what all the excitement is about. Why is GWT different from other framework-style solutions? GWT is more of a tool chain and a baseline technology rather than a particular application framework. So, although GWT has lots of libraries, you can use as many or as few as you find useful. Don't like GWT's UI? You can build your own using the DOM classes. Want to use JSON instead of RPC? It's easy. In fact, it is completely possible to start from scratch and build your own framework using GWT and benefit just as much from GWT's overall approach to debugging and compilation.
So, high-level, why should you consider using GWT for your next big web app?
We doubt you are someone who is easily influenced by mere assertions or marketing pitches, so we've put together the next few blog posts to take a look at exactly how GWT achieves these performance gains, and how it makes working with JavaScript easier.
Before we dive into the technical details, one last note. We sometimes get asked two questions about the very nature of GWT:
In answer to the first, understand that our goal and our passion is to radically improve the end user experience of the web, which means that GWT must produce JavaScript that is maximally performant and reliable. In order to do that, we naturally want to apply a lot of optimizations to source code and catch bugs as early as possible. Both of these goals are directly facilitated by Java's static type system and the existence of great Java IDEs. That is why we, dispassionately, chose to center GWT on Java technologies. That's it — no fodder for language wars here.
In answer to the second, it is perfectly reasonable that some developers, upon first hearing about GWT, assume that it is a sort of "walled garden of abstraction" that forever locks you into Java development and prevents you from using or integrating with handwritten JavaScript. Nothing could be further from the truth, which is a great segue...
You can easily combine handwritten JavaScript directly into GWT code. It's all JavaScript in the end, of course, so why not allow GWT developers to mix-and-match in any way that's useful? That's what JSNI is all about. It's named similarly to the Java Native Interface (JNI) because it uses the same basic idea: declare a Java method "native" and then use another language to implement it. In the case of JSNI, that other language is JavaScript.
JSNI is useful to create a reusable abstraction on top of functionality that is most naturally expressed using JavaScript syntax rather than Java syntax. For example, regular expressions are pleasantly concise in JavaScript, so you can use JSNI to make them directly available in your GWT code. Suppose you wanted a method to flip someone's name around such that their last name comes first, for example turning "Freeland Abbott" into "Abbott, Freeland". (Admittedly, this example is an I18N nightmare.) You can create a short JSNI method to do this:
// Java method declaration... native String flipName(String name) /*-{ // ...implemented with JavaScript var re = /(\w+)\s(\w+)/; return name.replace(re, '$2, $1'); }-*/;
Notice that the method body is really just a glorified Java comment, enclosed by the special tokens /*-{ and }-*/.
/*-{
}-*/
You can go the other direction, too, calling a Java method from JavaScript. Suppose we modified the example above to invoke a callback instead:
package org.example.foo; public class Flipper { public native void flipName(String name) /*-{ var re = /(\w+)\s(\w+)/; var s = name.replace(re, '$2, $1'); this.@org.example.foo.Flipper::onFlip(Ljava/lang/String;)(s); }-*/; private void onFlip(String flippedName) { // do something useful with the flipped name } }
Naturally, you can access any sort of external JavaScript code from within a GWT module. For example, if your HTML page looks like this:
<html> <head> <script> function sayHello(name) { alert("Hello from JavaScript, " + name); } </script> <-- Include the GWT module called "Spiffy" --> <script src="org.example.yourcode.Spiffy.nocache.js"></script> </head> ...
Within your Java source, you can access the sayHello() JS function through JSNI:
// A Java method using JSNI native void sayHelloInJava(String name) /*-{ $wnd.sayHello(name); // $wnd is a JSNI synonym for 'window' }-*/;
The GWT compiler inlines the extra method call away, so calling the sayHelloInJava() method in your Java source is no more expensive than calling sayHello() directly from handwritten JavaScript.
sayHelloInJava()
sayHello()
You can even create JavaScript-callable libraries from your GWT code. This is a pretty neat trick:
package org.example.yourcode.format.client; public class DateFormatterLib implements EntryPoint { // Expose the following method into JavaScript. private static String formatAsCurrency(double x) { return NumberFormat.getCurrencyFormat().format(x); } // Set up the JS-callable signature as a global JS function. private native void publish() /*-{ $wnd.formatAsCurrency = @org.example.yourcode.format.client.DateFormatterLib::formatAsCurrency(D); }-*/; // Auto-publish the method into JS when the GWT module loads. public void onModuleLoad() { publish(); } }
You can then access this GWT-created functionality from within any HTML page or another JavaScript library:
<html> <head> <-- Include the GWT module that publishes the JS API --> <script src="org.example.yourcode.FormatLib.nocache.js"></script> <-- Write some JS that uses that GWT code --> <script> function doStuff() { alert(formatAsCurrency(1530281)); } </script> </head> ...
Using JSNI, you can freely mix handwritten JavaScript, external JavaScript libraries, and Java source code in any way that you need to. That's what we mean we say GWT isn't a walled garden of abstraction and that you can adopt GWT incrementally into existing web apps. And, best of all, you can debug all the Java code using the Java debugger of your choice.
To learn more, check out JavaScript Native Interface in the GWT Developer Guide. Better yet, let GWT compiler architect Scott Blum explain it to you himself.