Skip to content

Step #2b: Updating the GWT Client to communicate with the Server

The next step is to update the client to communicate with the server side components. Again, if you’re not very patient, you can see the live client code at Colorado HomeFinder, and download the source.

I need to add a drop down, which will offer users the option of a 5/25 ARM rate, or a 30 year fixed rate. I need to have some way of decoding the JSON response from the server, and I need to update the interest rate text box with the results from the server.

Adding the drop down is fairly easy: Google provides a listbox. The listbox is an instance variable, rather than a local variable, and I also change the interest text box from a local variable to an instance variable. The reason: the change listener, which is a non static member class, has easier access to an instance variable than to a local one. Here’s the relevant code:

rateChoiceBox.addItem("5/25 ARM");
rateChoiceBox.addItem("30 Year Fixed");
rateChoiceBox.setVisibleItemCount(1);
rateChoiceBox.setWidth(width);
final RatesResponseHandler rrh = new RatesResponseHandler();
HTTPRequest.asyncGet(RATES_URL, rrh);

rateChoiceBox.addChangeListener(new ChangeListener(){
public void onChange(Widget sender) {
HTTPRequest.asyncGet(RATES_URL, rrh);
}
}
);
...
private class RatesResponseHandler implements ResponseTextHandler {

public void onCompletion(String responseText) {
boolean keepGoing = true;
JSONObject jso = null;
try {
jso = JSONParser.parse(responseText);
} catch (JSONException je) {
keepGoing = false;
// not sure what to do
}
String rate = "";
// ... get the data, put it into the rate variable.
MortgageCalc.this.interest.setText(rate);
}
}

In the RatesResponseHandler, I try to parse the JSON response that has been asynchronously downloaded from the server, and if I get meaningful text, I set the interest rate in the textbox: MortgageCalc.this.interest.setText(rate); If the server is not available, we still have a sane default. One interesting item: when you run the code with the server off in development, GWT pops you into the MS script debugger, which at least lets you know something is wrong.

The JSON processing code has already been written, so it made sense to leverage the JSON example that Google kindly provided. To do this, I made a few changes. Luckily, all the example code is made available under the Apache 2.0 license. You can find json.jar in the download, should you want to use it for a project of your own.

First, I wanted to make sure that none of the behavior of the EntryPoint JSON class occurred–I wanted the subsidiary libraries, but not the potato demostration. Therefore, I eviscerated the JSON class, and gave it an empty onModuleLoad method. On reading the module documentation, it appears this wasn’t needed–I could have just eliminated the <entry-point> entry.

Then, I started building the JSON code library. To pull in a set of external widgets, you need to do a couple of things.

  1. Build the library. I did this by compiling the JSON source, from the samples directory: mkdir builddir && javac -d builddir -classpath `cygpath -wp $PWD/bin/:.:../../../gwt-windows-1.0.21/gwt-user.jar` src/com/google/gwt/sample/json/client/JSON*.java. (The cygpath stuff is there because I’m developing on cygwin.) One thing to remember–you need to copy the java files into that same build directory: cd builddir/com/google/gwt/sample/json/client && cp ../../../../../../src/com/google/gwt/sample/json/client/*.java .. (Apparently you need the .class files for Eclipse or any other IDE, and you need to .java files so the Google compiler can compile the java to javascript. More here.) Also, don’t forget the JSON.gwt.xml, which should go in builddir/com/google/gwt/sample/json.
  2. Jar up the code, and place it in the classpaths. To compile from the command line, I added it to the Mortgage-compile.cmd batch file. For Eclipse development, I added it to the project buildpath (instructions for doing so). And I also had to add the json.jar file to the MortgageCalc application, so I could debug in Eclipse. To do this, choose ‘Run’ from the top menu, choose the ‘Run…’ option, select ‘MortgageCalc’, click the ‘Classpath’ tab, click ‘User Entries’ and add the jar using the Add button.
  3. Inherit from the JSON module. As far as I can tell, this isn’t inheritance in the usual object oriented sense, it’s more like importing packages in java. I did this by adding this line to the MortgageCalc.gwt.xml: <inherits name='com.google.gwt.sample.json.JSON'/> (I did try to use a source path to refer to the JSON classes, rather than inherit from them, but got this error:

    [WARN] Non-canonical source package: ../../../google/gwt/sample/json/client/

    [ERROR] Unable to find type ‘com.cohomefinder.gwt.mortgagecalculator.client.MortgageCalc’
    Hint: Check the inheritance chain from your module; it may not be inheriting a required module or a module may not be adding its source path entries properly

    )

After going through those steps, I could use the JSONParser and other JSON objects in my widget. Here’s the balance of the RateResponseHandler:

if (keepGoing && jso != null) {
int selected = MortgageCalc.this.rateChoiceBox.getSelectedIndex();
String [] keys = jso.getKeys();
if (keys.length == 2) { // expected
JSONValue jsvrate =
jso.get(keys[selected]);
JSONString jsstr = null;
if ((jsstr = jsvrate.isString()) != null) {
String rate = "";
if ((rate = jsstr.toString()) !=
null) {
//Window.alert("rate:
//"+rate);
MortgageCalc.this.interest.setText(rate);

}
}
}
}

The JSON parsing code is rather verbose. I also wasn’t a fan of the return values from the is* methods; I was always told that any method prefixed with ‘is’ should return a boolean. But then I peeked into the JSONParser class and decided that I’d just use the free code
and stop complaining. Final comments:

  • The module inheritance system is a quite powerful, if slightly
    misnamed, method of reusing code. In fact, there is already at least one blog about GWT widgets.
  • Packaging up code for a module is tedious, and perfectly suited to an
    ant task.
  • HTTPRequest is entirely adequate for pulling down data.
  • JSON, combined with HTTPRequest, gives you some typing, without tying
    you into a custom servlet. If you want typing stricter or more granular
    than javascript
    provides
    and are using a java backend, then Google’s
    services
    might be a better choice.