|
Tutorial_ExportingGwtLibrariesToJavascript_en
Exporting libraries developed in GWT to javascript.
IntroductionThere are several advantages to using GWT to produce high quality javascript code. For instance, the programmer does not need to be an expert in javascript, nor know peculiarities of each browser, or spend time packing, compressing, obfuscating, calculating dependencies, etc. And also, there are many advantages in publishing your library not only in java but in javascript, mainly because developers using other languages and frameworks, can take advantage of it without knowing anything about java and gwt. The relationship between GWT and javascript is the same than C and assembler. Why do you code in a low-level language which has different features for each platform, when you could do it in a high-level language, and give the compiler the responsibility of warning about mistakes, linking, optimising, obfuscating, and generating the most appropriate code for each platform?. Also, just as you can do with C inlining assembler, you can put javascript in your java code using JSNI.
The Basics
public class HelloClass implements EntryPoint{
String prefix = "Hello: ";
public void onModuleLoad() {
// Export the method when the application is ready
exportHelloMethod();
}
// Method that we want to use from javascript
public String helloMethod(String name) {
return prefix + " " + name;
}
// It is only used to create a reference in the browser to the final method
private native void exportHelloMethod() /*-{
$wnd.hello = function(name) {
return this.@jschismes.client.HelloClass::helloMethod(Ljava/lang/String;) (name);
};
}-*/;
}HTML code
package jschismes.client;
@Export
public class HelloClass implements Exportable {
String prefix = "Hello: ";
public String helloMethod(String name) {
return prefix + " " + name;
}
}HTML code
Using GWT-exporter
package jschismes.client;
@ExportPackage("jsc")
@Export
public class DatePicker extends GWTCDatePickerAbstract implements Exportable {
public void show(){
}
} <script language='javascript'>
var picker = new jsc.DatePicker();
picker.show();
</script>@Export
@ExportPackage("jsc")
public class DatePicker extends GWTCDatePickerAbstract implements Exportable {
public void show(){
}
}public class GWTCDatePickerAbstract implements Exportable {
@Export("foo")
public void initialise(){
}
} <script language='javascript'>
var picker = new jsc.DatePicker();
picker.show();
picker.foo();
</script>public class JsChismes implements EntryPoint {
public void onModuleLoad() {
((Exporter) GWT.create(DatePicker.class)).export();
}
}public class JsChismes implements EntryPoint {
public void onModuleLoad() {
onLoadImpl();
}
private native void onLoadImpl() /*-{
if ($wnd.jscOnLoad && typeof $wnd.jscOnLoad == 'function') $wnd.jscOnLoad();
}-*/;
} <script language='javascript'>
function jscOnLoad() {
var picker = new jsc.DatePicker();
picker.show();
}
</script>@Export
public class DatePicker extends GWTCDatePickerAbstract implements Exportable {
public String show(boolean a1, char a2, int a3, long a4, double a5, myClass a6){
}
}@Export
public class myClass implements Exportable {
}@Export
@ExportPackage("jsc")
@ExportClosure
public interface JsClosure extends Exportable {
public void execute(String par1, String par2);
}@Export
@ExportPackage("jsc")
public class DatePicker implements Exportable {
public executeJsClosure(JsClosure closure){
closure.execute("Hello", "Friend");
} <script language='javascript'>
var picker = new jsc.DatePicker();
picker.executeJsClosure(function(arg1, arg2) {
alert(arg1 + "," + arg2);
});
</script>@Export
@ExportPackage("jsc")
public class DatePicker implements Exportable {
Date currentDate = new Date();
public JavaScriptObject getCurrentDate(){
return timeToJsObject(currentDate.getTime());
}
public void setCurrentDate(JavaScriptObject date){
currentDate = new Date(jsObjectToTime(date));
}
private static native JavaScriptObject timeToJsObject(double time) /*-{
return new Date(time);
}-*/;
private static native double jsObjectToTime(JavaScriptObject d) /*-{
return (d && d.getTime) ? d.getTime(): 0;
}-*/;
} <script language='javascript'>
var picker = new jsc.DatePicker();
picker.setCurrentDate(new Date());
alert(picker.getCurrentDate());
</script>@Export
@ExportPackage("jsc")
public class DatePicker implements Exportable {
String caption = "Make your selection";
int type = 0;
public DatePicker(JavaScriptObject prop) {
JsProperties jsProp = new JsProperties(prop);
this.type = jsProp.getInt("type");
this.caption = jsProp.get("caption");
});
} <script language='javascript'>
var picker = new jsc.DatePicker({
type: 1,
caption: "Select a date"
});
</script>public class JsProperties {
JavaScriptObject prop = null;
JsProperties(JavaScriptObject properties) {
this.prop = properties;
}
public String get(String name) {
return getImpl(this.prop, name);
}
public int getInt(String name) {
String val = get(name);
return val == null ? 0 : Integer.valueOf(val);
}
private static native String getImpl(JavaScriptObject p, String name) /*-{
return p[name] ? p[name].toString() : p[name] === false ? "false" : null;
}-*/;
}Creating and configuring the GWT module to exportIt is recommended that you create a new module to export your GWT library. In fact, it is better not modify your original GWT library, so you can publish it as a '.jar' file without depending on gwt-exporter. These are the steps to do that:
<module> <inherits name="com.google.code.p.gwtchismes.GWTChismes"/> <inherits name="org.timepedia.exporter.Exporter"/> <set-porperty name="export" value="yes"/> </module> @Export
public class Alert extends GWTCAlert implements Exportable {
private JsProperties jsProp;
public Alert(JavaScriptObject prop) {
super();
this.jsProp = new JsProperties(prop);
if (jsProp.defined("className"))
super.setStyleName(jsProp.get("className"));
}
public void show(int seconds) {
super.show(seconds);
}
public void alert(String msg) {
super.alert(msg);
}
public void hide() {
super.hide();
}
}<module> [...] <entry-point class="jschismes.client.JsChismes"/> </module> public class JsChismes implements EntryPoint {
public void onModuleLoad() {
((Exporter) GWT.create(Alert.class)).export();
onLoadImpl();
}
private native void onLoadImpl() /*-{
if ($wnd.jscOnLoad && typeof $wnd.jscOnLoad == 'function') $wnd.jscOnLoad();
}-*/;
<module> [...] <add-linker name="xs"/> </module> Note: So far GWT 1.6.x & 1.7.0 don't support xs linker in hosted mode, so you have to comment this line at development time, or you can create another .gwt.xml file for this purpose. Documenting the produced LibraryUnless java packages that can be easily used letting the java IDE make suggestions about the classes, methods, parameters, etc, to make use of a javascript library it is necessary to have a little documentation about the usage of it. So, don't forget to create and maintain the appropriate documentation of your library. Unfortunately there isn't any tool to produce this documentation automatically, but you can document your library in the java code using some proprietary conventions, and then create your own parser to produce a wiki markup page. I use this technique and a home-brewed ugly perl script to do that. References and examples
©2009 Manolo Carrasco Moñino |
Sign in to add a comment