Upgrading to GWT 2

I recently had the pleasure of upgrading from GWT 1.5.3 to GWT 2.0.  The client has a variety of GWT applications–some standalone widgets that integrate into an existing site, an application written with GWT look and feel, and an application written with the GWT-EXT library.

The upgrade to GWT 2.0 was much less painful than I thought it would be.

Even code that was written for GWT 1.0 (the mortgage calculator, written back in 2006) compiled cleanly (well, plenty of warnings, but no loss of functionality).  Classes that have been deprecated (some for good reason; hello HTTPRequest, I’m looking at you) have not disappeared.  I’m not saying that the code I wrote for GWT 1.0 shouldn’t be rewritten, just that GWT hasn’t forced me to do so.  Also, other than changing some switches to the command line compiler, the ant script used to compile the GWT modules didn’t have to change at all.

Hosted mode was a different story.  I never really spent a ton of time in hosted (err, dev) mode, but had it working in that past.  Now, I wanted to get it working fully because of the tremendous productivity gains possible–no minute long compile cycle to pull my attention away from my code.  And the fact that you can run and debug in eclipse in more than just one browser is really attractive.  Since I’d never really had it working fully, there wasn’t a lot of upgrade work; it was more like starting from the beginning.  However, I was unable to use the internal jetty server.  Again, my use case is atypical, with a lot of JSON and JSONP requests for data.

Big pluses for GWT 2.0, right off the bat:

I haven’t yet looked into Speed Tracer or some of the updated widgets (I’d really love to toss the gwt-widgets lightbox we use in favor of the GWT standard PopupPanel).  There’s also the tremendous benefit of being on the modern version of any platform–it is easier to get support in forums and in other venues.


GWT widgets and code splitting, a match made in heaven

If you are writing a typical GWT application, which is monolithic and controls the entire viewport of the browser, you probably don’t want to read this post.  Go on, read something else interesting–you probably have emails or tweets or something better to do with your time.

OK, now we just have the people left who are using GWT to build widgets; that is small encapsulated pieces of functionality that integrate into an existing web based application (case #2 outlined here).  If you’re doing this, and you use the “span to enable” gwt mini pattern, you want to upgrade to GWT 2.0 simply to get the new code splitting functionality.  If you don’t want to read that previous link, the synopsis is that code splitting lets you define a number of pieces of distinct code, using GWT.runAsync.  Then, that code won’t be downloaded until it is reached.

Previous to this feature, if you had a number of widgets, you ended up with a large chunk of code to download on every page (this is an issue with GWT that the monolithic applications simply don’t have to deal with).  Some of that code will be run.  Some will not, but you’re still paying for download and parsing of that code.  You had some unsavory options to deal with this–let all the code be downloaded, or manually split up code into separate modules that you managed (either by hand or with deferred binding).  The second solution led to smaller downloads, but meant a lot more management–if you wanted to add a widget to a page, you not only had to add the enabling span, you had to recompile the entire GWT module–and much longer compilation when you deployed your entire web application.  However, if your widgets were static, this path might have been an option.

My client used the former solution (entire code download on every page), and was very excited about the code splitting, since that essentially automates the second choice above.  In the space of about one half hour, I was able to reduce the initial download size of the GWT javascript by 10%, and there’s scope for much more, since the code is pretty naturally split up into separate chunks for each widget.

It’s not perfect, however. The two concerns I’ve had so far:

  1. The XS linker is not supported.  This means that if any of your widgets need to be cross domain, you need to create an additional module specifically for that.  For example, if I have one module, A, which is used to start up all the widgets on the site, and inherits from both module B, which has some GWT code split calls, and module C, which needs to be cross domain, the compiler will error out when compiling module A.  I need to create a second module XSModuleC which inherits from module C and is compiled by the XS linker, and then use that module for all cross domain purposes.
  2. If you call GWT.runAsync from an event handler, like onClick, you will not have a valid event on the first call (when the module is loaded) but will on all subsequent calls.  This is easy to fix, but was a bit mystifying to me.  Basically, if you have code like this:

onClick(ClickEvent event) {
if (event.getSource() instanceof Image) {
// do something with image
}
}

you need to replace it with:

onClick(ClickEvent event) {
if (event.getSource() instanceof Image) {
// save event.getSource into an instance variable
GWT.runAsync(new RunAsyncCallback() {
// do something with image in instance variable
}
}
}

I'm sure there are other complications I'll find once I do more code splitting.  (Here's an interesting post about code splitting in large applications, and simplifying the API of code that is split (plus, you get to see the word cromulent in context).)  But, for now, code splitting and GWT widget development seem like a match made in heaven.

Technorati Tags: ,


Finding supported GWT user.agent values

The GWT compile process has been taking longer and longer, as I’ve moved from 1.0 to 2.0, because they keep adding optimizations and functionality.  You could deal with this in a number of ways.  You could write less GWT.  You could buy a faster computer.

More realistically, you could live in your IDE, and run in development (nee hosted) mode.  However, sometimes you just have to test with javascript.  The external browser development environment can be tough to set up correctly, especially if your application depends on external resources, and you can run into weird bugs.  I’m currently dealing with an issue where I depend on an external library and it is consistently throwing an assertion exception in development but runs fine in production mode.

If I am compiling to javascript repeatedly, I often compile for just one user-agent, which saves about 80% of the compile time.  When I have code more put together, I can compile for all other browsers.  This process is not flawless, as I am currently debugging a cross browser issue (something that works fine on FF doesn’t work on Safari) but I probably wouldn’t have tested on Safari until after I was through the lion’s share of development anyway.

The way to target just one browser is to put this string in your module (.gwt.xml) file:

< set-property name="user.agent" value="safari,ie6,gecko1_8" / > (remove the spaces next to the angle brackets)

How do you find valid values?  Via this thread, I found that you look in UserAgent.gwt.xml, part of the gwt-user.jar file.  This has the javascript code that looks at navigator.userAgent.  It is not as fine grained as the ubiquitous browser detect script, but shows you what different browsers are known to GWT.

For other tips on speeding up the compile process, check out this series of posts.

Technorati Tags: , , ,


New Release of GWT Crypto Library

I just released a new version of gwt-crypto.  You can download it here.  While encryption in javascript has its limits, it also has its place.  Currently, I am using it for some data (lat/lng) that we want to be obscured, but is not top secret.

If you’re using this library, please let me know what you’ve found it useful for.
Overall, this has been a fun experience.  I’ve learned at least the basics of maven, had some interaction with users and written tests for bugs they file.  (I got involved in this project earlier this summer, because I contacted the maintainer.)

Technorati Tags: , , ,


Article about using hibernate with GWT

I just read this article about the Google Web Toolkit and hibernate, and I’m thrilled that someone wrote this. A few years ago, when I was just starting to use GWT and hibernate, the ORM tool, I thought about writing something similar myself. I could never get over the hump of writing about setting up all the infrastructure necessary, something which the author does quite nicely.

I think this article gives a great overview of some of the complexities of using hibernate with the GWT client. The author essentially talks about three possible solutions to the primary problem when using hibernate objects in a GWT system: hibernate enhances your POJO code, and thus you cannot send objects returned from hibernate queries down the wire to the JavaScript client.  The JRE emulation simply can’t handle it.

I especially enjoyed the explanations of how to use some of the tools, to make mapping between GWT capable objects and hibernate objects easier. I’d heard of hibernate4gwt, now Gilead, but never used it. For most of my RPC calls, I end up using the first approach the author explores, custom DTO creation. Often times, I won’t create a special DTO object, but rather reuse the POJO that represents the domain object. This way, you can scrub subsidiary objects (though you lose lazy loading when you do this) and send those down as well.  As long as the POJO doesn’t have too many extraneous members, this seems to work fine, and removes the need for an extra class.

I was a bit frustrated, however, that the author ignored the delete case. This seems like a situation where tools like Gilead might really shine. I have often run into issues where I have to add a ‘deleted’ boolean flag to the hibernate object.  I do this because when an object gets deleted from a collection on the GWT side, my server-side code has no way of knowing this, without some additional complexity (rerunning the query and doing a comparison of results). Adding such a ‘deleted’ boolean flag, solves one set of problems, but raises additional complexity, because you end up having to check to see whether or not an object exists before you try to insert it in the database.

For example, imagine you have a user with set of CDs, which you display in a grid.  If you want to allow a user to correct the name of one of the CDs, and send it back, the server side has the modified record, hopefully with and ID, and can simply save it.  But if you delete one of the CDs from the collection, the server side does not have the modified object, and so has to figure out which one to delete.  Gilead, with its knowledge of the object graph, seems at first glance like it could solve this problem elegantly (a quick search on the Gilead site shows nothing that I could see).

Also note that, using RPC is fantastic for GWT applications, but if you think about using GWT for widgets, I would suggest using something that gives you a bit more flexibility like JSONP. Because GWT RPC depends on XMLHTTPRequest, it is fundamentally limited to sites where the JavaScript and RPC services are on the same host.  Obviously, since using JSONP serializes hibernate objects to strings, none of these tools are appropriate.  (See my survey of Google Web Toolkit client-server communication strategies for more.)

All that said, if you’re thinking about using hibernate and GWT in the same project, reading this paper and running through the examples will be a worthwhile use of your time.

Technorati Tags: , ,



GWT and complex javascript overlays

I remember hearing about javascript overlays and the Google Web Toolkit at the 2008 Google I/O conference, so when I had a chance to use them for a complicated JSON dataset, I thought it would be a good fit.  I use JSON in a number of widgets around a client’s site, mostly because it is the easiest way to have a client be cross site compatible (using JSONP for server communication), the data ranges in size from 13K to 87K.

But as I looked for examples, I didn’t see a whole lot.  There is, of course, the canonical blog post about javascript overlays, but other than that, there’s not much out there.  I searched the gwt google group, but didn’t see anything about complex javascript overlays.

Perhaps I should define what I mean by complex javascript overlays.  I mean JSON objects that have embedded objects and arrays; something like this: var jsonData = [{"id":52,"display":{"desc":"TV","price":125},"store":[1,2,3,4,5]}, {"id":2,"display":{"desc":"VCR","price":25},"store":[1,2,5]}];

The key is to realize that just as you can return a string from a native method, like the canonical blog post does: public final native String getFirstName() /*-{ return this.FirstName; }-*/;, you can also return any other javascript object, including arrays (helpfully available as the JsArray class).  So, for the above JSON example, I have a Display class that looks like this:

package com.mooreds.complexoverlay.client;
import com.google.gwt.core.client.JavaScriptObject;

public class Display extends JavaScriptObject {
protected Display() {}
public final native String getDesc()/*-{ return this.desc;}-*/;
public final native int getPrice()/*-{ return this.price;}-*/;
}

Code for the array ("store") looks like this:

package com.mooreds.complexoverlay.client;

import com.google.gwt.core.client.JsArrayInteger;
public class StoreList extends JsArrayInteger{
protected StoreList() {}

}

Running code that shows you how to parse and display the entire json string is here (using GWT 1.6.4) is available in this tarball.  I haven't yet tried it, but I imagine that it would be pretty easy a JSONP call work in a similar manner to the HTML embedded JSON in this example.

Update June 29: Note that if you want to use any overlay types in collections, that JavaScriptObject, which you must inherit from, has final hashCode and equals methods.  The hashCode method "uses a monotonically increasing counter to assign a hash code to the underlying JavaScript object" and the equals method "returns true if the objects are JavaScript identical (triple-equals)".  Both of these may cause issues with collections such as maps.

Technorati Tags: , , ,


GWT encryption options

I was looking for an encryption package for GWT.  A client had some mildly private information that they wanted to encrypt in transmission.  Now, of course, this is ultimately futile.  Anyone who wants to get at this information can, because we send the source code (however obfuscated) that decrypts the information to the client.  To borrow Corey Doctorow’s words, the attacker is also the recipient.  But, sometimes just making getting the information inconvenient is good enough.

I looked at a couple of encryption options.  There’s are a couple of nice javascript libraries that do encryption: Gibberish-AES and javascript.crypto.library, but they hav no GWT hooks (and javascript.crypto.library is released under the AGPL which has some unclear legal ramifications).

However, there is a project from about two years ago that does Triple DES encryption and is written in pure GWT.  It’s even called gwt-crypto.  Unfortunately, it hasn’t been maintained recently.  I was able to download the files, apply a fix (for issue #1) and move some files around in such a way that it works.

Here’s how you use it:

on the server:
TripleDesCipher cipher = new TripleDesCipher();
cipher.setKey(Constants.GWT_DES_KEY);
try {
enc = cipher.encrypt(String.valueOf(value));
} catch (DataLengthException e1) {
e1.printStackTrace();
} catch (IllegalStateException e1) {
e1.printStackTrace();
} catch (InvalidCipherTextException e1) {
e1.printStackTrace();
}

On the client, make sure you inherit the module:
<inherits name='com.googlecode.gwt.crypto.Crypto'/>
Then:

TripleDesCipher cipher = new TripleDesCipher();
cipher.setKey(Constants.GWT_DES_KEY);
String dec ="";
try {
dec = cipher.decrypt(enc);
} catch (DataLengthException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (InvalidCipherTextException e) {
e.printStackTrace();
}

I just use a constant DES key, which is not all that secure.  I’m sure you could do something more secure like hashing the request time, filename and some other secret key, but you need to make sure that both the server and the client agree on the key, otherwise you’ll not be able to decrypt the info.

Update 6/13: I got permission from the project owner to update the google project, so I’ve done that.  You can download the new gwt-crypto jar there.

The modified gwt-crypto jar file is here.  I’m hoping the administrator will let me at least check in the changes I’ve made so that it works on GWT 1.5.3 (can’t speak for GWT 1.6).

Technorati Tags: , ,


Popups in GWT and IE8

Just starting to test some GWT applications against IE8.  (Using IE Collection, which is very useful.  It includes standalone versions of IE from IE1 to IE8.  Very useful, even if the version of IE8 doesn’t include the developer tools.)

The only issue I’ve seen so far is that popups don’t work correctly.  Some appear, but not where they are supposed to.  Others, particularly with the lightbox we’re using (from the GWT-Widget project), just don’t appear at all.

For the latter, you get the very helpful message:

Line: 2618
Char : 324
Error: Not implemented
Code: 0
File: url to your GWT cache.js file.

(This is with GWT 1.5.3.)  After compiling the GWT with “-style DETAILED”, I looked at the precise line causing the error message.

It was in this method:

function com_google_gwt_user_client_ui_impl_PopupImplIE6_$onShow__Lcom_google_gwt_user_client_ui_impl_PopupImplIE6_2Lcom_google_gwt_user_client_Element_2(popup){
var frame = $doc.createElement($intern_1350);
frame.src = $intern_1351;
frame.scrolling = $intern_1352;
frame.frameBorder = 0;
popup.__frame = frame;
frame.__popup = popup;
var style = frame.style;
style.position = $intern_1314;
style.filter = $intern_1353;
style.visibility = popup.style.visibility;
style.border = 0;
style.padding = 0;
style.margin = 0;
style.left = popup.offsetLeft;
style.top = popup.offsetTop;
style.width = popup.offsetWidth;
style.height = popup.offsetHeight;
style.zIndex = popup.style.zIndex;
/*
style.setExpression($intern_110, $intern_1354);
style.setExpression($intern_111, $intern_1355);
style.setExpression($intern_91, $intern_1356);
style.setExpression($intern_93, $intern_1357);
style.setExpression($intern_1358, $intern_1359);
*/
popup.parentElement.insertBefore(frame, popup);
}
You can see where I commented out the style.setExpression calls, which seemed to fix the issue (the $intern strings are css property names like 'left').  Obviously not very sustainable. The other fix available right now is to add this meta tag to the HEAD section of your HTML documents:
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />

For more information on this, follow the GWT issue tracker bug 3329.


GWT Server Communication Strategies

I have been doing a fair bit of GWT wrangling lately, but noticed my blog didn’t reflect that.  I thought I’d do a broad survey of GWT server communication strategies.  By server communication, I mean the ability to transfer data to or from or to and from a server.

Since GWT is, at the end, just javascript, these methods that work, work for any javascript code (those that don’t work may fail due to GWT strictures).  But I’ll be looking at them with a particular GWT focus.  I created a sample Eclipse project that shows all of these methods (except for GWT-RPC, since that is so well documented and requires a java server).  I encourage you to download it and toy around with each of these methods.  I used GWT 1.5.3 on Windows, and tested the code in both in the hosted browser and my normal browser (FireFox 3).

For the anxious and impatient, here’s a quick table overview.

Method To server From server Cross domain Payload length Notes
HTTP request yes yes no unlimited (post) developer responsible for making sense of data
GWTRPC yes yes no unlimited (post) only works with java server on the backend
JSON yes yes yes limited by URL length (2048) hard to determine when data is loaded
JSONP yes yes yes limited by URL length (2048)
Form yes yes/no yes unlimited payload no server response available if posting cross domain
Iframe yes yes no limited by URL length cross domain fails

HTTP requests are the simplest way to retrieve data from the server.  The data retrieved can be anything (text, HTML, JSON, XML, some other data format, binary data, etc), but you as a developer are responsible for taking that data and turning it into something your program can use.  Also, since HTTP requests use XMLHttpRequest under the hood, you are limited to the same hostname that your GWT code was served from.  This is the default setting for most browsers (the so called Same Origin Policy)–I did notice that the GWT hosted browser does let you pull HTTP Requests from a different domain, after a warning.  FF3 does not allow the cross domain request at all–it fails without an error message.  Data transmission is two way.  The GWT documentation provides sample code.

GWT-RPC is the method that is given the most attention in the GWT docs.  GWT-RPC provides plumbing to marshal and unmarshal java java objects marked with the Serializable or IsSerializable interfaces.  The data object can’t contain any fields that GWT doesn’t know how to translate, like URI.  GWT-RPC is currently built on XMLHttpRequest and is subject to all of its benefits and limitations.  Data transmission is two way.  The GWT documentation contains sample code.

JSON is a data interchange format that encodes data in a way that can be executed by javascript compilers.  It looks something like this:

var myvar = {"msg":"plain json"};

GWT can use JSON to pull data from remote servers.  Data can be transmitted both ways, but in GWT it is hard to know when the data has been returned from the remote server.  (Also, there are some security implications.  Read the article linked to above.)  You can poll via a Timer to see if a variable has been created. (This is tedious, but may be the best option when the server JSON output is not under your control.)  The closely related JSONP method uses a function instead of a javascript variable, and removes the need for any Timer.

JSONP takes JSON the next step farther and adds a callback function into the mix.  That way, when the remote data has been loaded, a javascript callback function will be executed.  It looks something like this:

my_fcn({"msg":"plain jsonp"});

When the script is loaded, the json is executed, and my_fcn will be executed as well.  I’ve used this quite successfully to make GWT widgets pull data across domains.  This excellent article has an almost complete implementation.  The only thing missing is removing the scrip tag when the callback function is called.  My code just associates a uniqueId with every script element.  After the JSON is parsed, the element is removed.

private native void removeScript(String uniqueId) /*-{
var elem = window[uniqueId+"DOMELEM"];
if (elem != null) {
document.getElementsByTagName("body")[0].removeChild(elem);
}
}-*/;

Form Submission is a method of server communication that really excited me, because I know that in HTMLland, you can do cross domain posts rather easily.  In theory, this means you don’t have to jump through the hoops of JSONP, and can have large amounts of data sent.  Alas, it was not to be.  You can post forms cross domain, but “The result html can be null as a result of submitting a form to a different domain.”  The data does get to the server, though.  If you are trying to get a large amount of data cross domain, this may be useful, but you’ll have to use some kind of polling with JSON or JSONP to determine that the server has handled that data in the way you expected it to.

IFrames were the original remote scripting solution and GWT supports them…kinda.  I was surprised to learn that a cross domain iframe failed in the hosted browser with a security exception.  It also fails in FF3 with the exception: “Permission denied to get property Window.document”.

I hope this tour of GWT server access methods and code is useful to you.

Technorati Tags: , ,



© Moore Consulting, 2003-2019