PermGen error

GWT 2, JSONP and Javascript Overlays with JsonpRequestBuilder

In one of my earlier posts I discussed the topic of making cross site requests with Google Web toolkit.

Since that post Google have updated Web toolkit, currently version 2.0.3 and has now made it easier to make cross site requests through the use of their new JsonpRequestBuilder object and the Javascript object overlay types for result encapsulation.

This is a quick tutorial update on how to make use of the object overlay types. The application contacts the Geonames webservice. For the example I shall use the ‘Placename lookup with postalcode (JSON)’ function by making the following call:

http://ws.geonames.org/postalCodeLookupJSON?postalcode=M1&country=GB&maxRows=4

This returns location details for places matching the M1 post code so central Manchester in the United Kingdom.

The results this request return are as follows:

{"postalcodes":[
{"adminCode3":"BN","adminName3":"Manchester District (B)","adminCode2":"00","postalcode":"M1 1AD","adminCode1":"ENG","countryCode":"GB","lng":-2.24521599415295,"placeName":"City Centre Ward","lat":53.4838491117407,"adminName1":"England"},
{"adminCode3":"BN","adminName3":"Manchester District (B)","adminCode2":"00","postalcode":"M1 1AE","adminCode1":"ENG","countryCode":"GB","lng":-2.23116928236428,"placeName":"Ancoats and Clayton Ward","lat":53.4834816441844,"adminName1":"England"}
]}

If you look at the previous JSON data it seems we have a list of ‘postalcodes‘ and each postal code has various fields such as adminName3, placeName etc.

Using GWT Javascript object overlays we can represent this structure. Within your GWT client directory create a new class called PostcodeEntry and add the following:

import com.google.gwt.core.client.JavaScriptObject;
 
public class PostcodeEntry extends JavaScriptObject {
 
	protected PostcodeEntry() {}
 
	public final native String getAdminCode3() /*-{
		return this.adminCode3;
	}-*/;
 
	public final native void setNumberPlaceHolderId(String adminCode3) /*-{
		this.adminCode3 = adminCode3;
	}-*/;
 
	public final native String getAdminName3() /*-{
		return this.adminName3;
	}-*/;
 
	public final native void setAdminName3(String adminName3) /*-{
		this.adminName3 = adminName3;
	}-*/;
 
	public final native String getPostalcode() /*-{
		return this.postalcode;
	}-*/;
 
	public final native void setPostalcode(String postalcode) /*-{
		this.postalcode = postalcode;
	}-*/;
 
	public final native String getPlaceName() /*-{
		return this.placeName;
	}-*/;
 
	public final native void setPlaceName(String placeName) /*-{
		this.placeName = placeName;
	}-*/;
}

Each PostcodeEntry represents one postalcode as you can see we have the functions for the various properties of a postalcode. Also note we extend the GWT JavascriptObject. In the above example you’ll notice I haven’t implemented every property. This is by choice I have only implemented a few of the properties.

Now we need to build an object that maintains the collection of PostcodeEntry object. Essentially the object that represents the postalcodes array. Create a new Java object called ‘PostalCodes‘. Add the following content:

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
 
 
public class PostalCodes extends JavaScriptObject {
 
	protected PostalCodes() {}
 
	public final native JsArray<PostcodeEntry> getPostalCodes() /*-{
    	return this.postalcodes;
  	}-*/;
 
}

The object quite simply has one method called getPostalCodes which you’ll notice is a collection of PostcodeEntry objects and the native method simply called this.postalcodes which if you remember was the name of the array in the JSON response.

Those two objects wrap up the Geonames JSON response.

Finally we just need to write the code that invokes the service using the JsonpRequestBuilder object.

Locate your GWT entry point and add the following code.

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.jsonp.client.JsonpRequestBuilder;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
 
/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class JsonpExample implements EntryPoint {
    /**
     * This is the entry point method.
     */
    public void onModuleLoad() {
        //
	// http://ws.geonames.org/postalCodeLookupJSON?postalcode=M1&country=GB&maxRows=4
	//
	JsonpRequestBuilder jsonp = new JsonpRequestBuilder();
 
        String url = "http://ws.geonames.org/postalCodeLookupJSON?postalcode=M1&country=GB&maxRows=4";
 
	jsonp.requestObject(url, new AsyncCallback<PostalCodes>() {
	    @Override
	    public void onFailure(Throwable caught) {
                Window.alert("Failure:" + caught.getMessage());
            }
 
            @Override
            public void onSuccess(PostalCodes result) {
                VerticalPanel vp = new VerticalPanel();
		if(result.getPostalCodes() != null ) {
                    for( int count = 0; count < result.getPostalCodes().length(); count++) {
			PostcodeEntry entry = result.getPostalCodes().get(count);
			HorizontalPanel hp = new HorizontalPanel();
			hp.setSpacing(10);
			hp.add(new Label(entry.getPostalcode()));
			hp.add(new Label(entry.getPlaceName()));
			vp.add(hp);
		   }
               }
               RootPanel.get().add(vp);
           }
       });
    }
}

There are few important areas of this code to take note.

First of all note the use of the JsonpRequestBuilder object. We simply give this a Url which in this case is the Geoname service url. Those who are familiar with cross site requests will notice that the URL I specified doesn’t contain the ‘callback’ parameter. The JsonpRequestBuilder automatically appends this to the end of the URL for us so we have &callback=gwt_IOSucess appended to the request. It defaults the parameter name to ‘callback’ but if the service requires a different parameter name you can change this by calling setCallbackParam.

Next we simply call requestObject that takes an Async callback which is of our Postalcodes type. This clears up why we use object overlays.

Finally the onSuccess method takes in the Postalcodes as an argument and we are then free to pick away at the response and the various postalcode entries in the result.

I hope this has helped people to start making use of the new GWT JSONP functions and object overlays.

You can also download the source code for this example.

Please any comments welcome…..


Categorised as: Google Web Toolkit


15 Comments

  1. Quan says:

    OMG! I love you! I was battling SOP for quite a while now, but thanks to your post I could finally get it done. Thanks a lot!

  2. [...] added in GWT 2.0 making these types of cross site requests easier to implement.  Here’s a very well written post showing how to do this (yes, I’m lazy and he obviously knows a lot more about these than I do [...]

  3. admin says:

    @JC

    Thanks I’m glad you found it useful! :)

  4. JC says:

    Great post and examples! Just used it on my project which interacts with a web service written in Python/Django running on a different server.

    Thanks for sharing this!

  5. MeloD says:

    Hi again,
    Thanks for the reply. I just downloaded the sample code and ran it.
    First attempt gave me the error message “Failure:Timeout while calling http://ws.geonames.org/postalCodeLookupJSON?postalcode=M1&country=GB&maxRows=4“.
    Second attempt (refresh), it worked. So I guess now I should look for some issues in my own code…

  6. admin says:

    @MeloD
    Hi there

    The GWT code should append the callback parameter to the request for you?

    “Those who are familiar with cross site requests will notice that the URL I specified doesn’t contain the ‘callback’ parameter.”

    in terms of the timeout have you tried downloading the example code and seeing if that works or did you try coding your own solution from the sample code here?

    Example code

    http://eggsylife.co.uk/JsonpExample.zip

    Eggsy

  7. MeloD says:

    Hi,

    Thanks for the great article. Before I apply this method to my own code, I tried to see if I can run the example here. So, I imported both PostalCodes.java and PostcodeEntry.java files into my project and added the last code segment into its respective place in my own code. Through debugging, I can see that everything goes fine, except I always receive a server Timeout failure (I am using the same URL provided here).

    Might it be related to this issue?
    http://code.google.com/p/google-web-toolkit/issues/detail?id=6382

    As I can see here and also checking the URL itself, the returned response from the server is not padded in a ‘callback’ name, nor does it end with a semicolon…

  8. Riyaz says:

    @Nagaraj
    Hey Nagaraj facing the same issue, did you find any solution to it ?

  9. admin says:

    @Prasad

    The JsonpRequestBuilder does have a setTimeout option so it might be worth increasing that if the Digg service is taking its time to respond?

    Eggsy

  10. Prasad says:

    Hi Thanks for the article, I followed what you have done but I wrote getters and setters to fit with the api that i am working on (http://services.digg.com/2.0/story.getTopNews) i am getting a server time out error. I use the url exactly I typed here. Any help would be greatly appreciate.

    Thanks
    prasad

  11. brian balote says:

    worked perfectly for me, thanks for sharing! keep it up! :)

  12. admin says:

    Hi Nagaraj,

    I’m not too sure what you are asking.

    The code above is all client side and it is representing the Server side JSON – taken from the Geonames API – and converting it to client side object.

    Notice the onSuccess method refers to a ‘PostalCodes’ object as its parameter. This is a fully populated object based on the server side JSON.

    Eggsy

  13. Nagaraj says:

    Very good introduction to calling REST using GWT and parsing JSON output. If the JSON output is a complex object structure how do we map the output to the objects? I use JAXB annotations and that converts a JSON input to the REST service to object structure automatically. But, I need something like that on the client side using GWT.

    Thanks in advance.
    Nagaraj

  14. Would love to see more about this, e.g. binding UI components to custom services running on a different server as well as cross-site Ajax.

    Thanks for sharing your work. :-)

    Marc

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">