Wednesday, March 03, 2010

Building a GWT Declarative Interface

Introduction

GWT 2 has introduced the concept of declarative interfaces, that is, the interface can be described via an XML document, rather than built using code. The idea isn't new, it's seen in many new technologies such as Macromedia Flex, ASP.Net and JavaFX, however to the GWT developer it means the end of writing reams of boiler plate code.

In this post I show you how to create a simple Image Gallery widget that has a declarative interface and then how to create bigger interfaces using these widgets.

The Basic Widget

Before we do anything, we need to define the basic ImageGalleryWidget, in our case, it looks as so :

public class ImageGalleryWidget extends Composite {
 private GalleryImage[] images;
 private int currentImageIndex = 0;
 
 public ImageGalleryWidget() {
 }
 
 public void setTitle(String value) {
 }
 
 public void setImages(GalleryImage[] images) {
  this.images = images;
  currentImageIndex = 0;
 }
 
 public static class GalleryImage {
  private final String caption;
  private final String url;
  
  public GalleryImage(String url, String caption) {
   this.caption = caption;
   this.url = url;
  }
  
  public String getUrl() {
   return url;
  }
  
  public String getCaption() {
   return caption;
  }
 }
}

As you can see, our ImageGallery has two properties: a title, and an array of images to display. Each image has the URL of the actual file, and a caption. You'll also notice that our widget doesn't extend Widget but rather Composite, this is important as we'll see later.

Defining the Interface

GWT allows you to use the declerative method to define interfaces of individual components, in this case the interface for a particular widget. Before we go any further, it would be a good idea to show the UI for our image gallery:

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' 
      xmlns:g='urn:import:com.google.gwt.user.client.ui'>

  <g:VerticalPanel spacing="3">
   <g:Cell horizontalAlign="CENTER" cellSpacing="40" width="100%">
    <g:Label ui:field="title"/>
   </g:Cell>
   <g:Cell>
    <g:Image ui:field="image"/>
 </g:Cell>
 <g:Cell width="500px">
    <g:HorizontalPanel spacing="5" width="100%">
     <g:Cell>
      <g:Button text="Prev" ui:field="btnPrev"/>
     </g:Cell>
     <g:Cell>
      <g:Label ui:field="caption"/>
     </g:Cell>     
     <g:Cell>
      <g:Button text="Next" ui:field="btnNext"/>
     </g:Cell>
    </g:HorizontalPanel>
 </g:Cell>  
  </g:VerticalPanel>
</ui:UiBinder>

First lets look at the namespace declarations. The first binds the prefix ui to urn:ui:com.google.gwt.uibinder which identifies GWT specific elements to the parser such as the UiBinder element; it will be required on every declared interface file. The next namespace urn:import:com.google.gwt.user.client.ui imports elements from the com.google.gwt.user.client.ui package, (the standard GWT Widget package) to be used in the interface. You can see some of these objects in use such as g:VerticalPanel. We'll come back to imported elements later.

Inside the UiBinder element you define your interface by specifying widgets to be instantiated. In this case we're creating a standard VerticalPanel widget with Cells for each row. In the top cell we're adding a label, the next we're adding an Image, and the bottom cell holds a HorizontalPanel which contains the Prev and Next buttons. As you'll appreciate, this interface file is a lot easier to read and modify than if it had been defined in standard Java.

Certain elements in our file have a special ui:field attribute defined. This is a special declarative attribute which tells GWT which field within the associated Java class (we'll get to that shortly), should hold a reference to that component.

Our widget is called ImageGalleryWidget and therefore the declarative XML file should be saved in the same package with the name ie. ImageGalleryWidget.ui.xml

Binding To A Java Class

The XML defines the UI, however a UI doesn't exist by itself, we need a way of referencing elements so that we can set and retrieve properties. In order to do this we need to add elements to the ImageGalleryWidget :

public class ImageGalleryWidget extends Composite {
 interface ImageGalleryUiBinder extends UiBinder<VerticalPanel, ImageGalleryWidget> {}
 private static ImageGalleryUiBinder uiBinder = GWT.create(ImageGalleryUiBinder.class);
 
 @UiField Image image;
 @UiField Label caption, title;
 @UiField Button btnNext, btnPrev; 

 // .... Rest Ignored ... 
} 

The first line defines an interface which will act as the binder, that is, it will set the field elements annotated by UiField. An implementation of this interface will be created by the GWT compiler. The second line is a standard GWT deferred binding create statement need to instantiate the generated binder class.

The next thing we need to do is perform the binding magic to apply values to our UiFields. This is done using the binder as so :

 public ImageGalleryWidget() {
  initWidget(uiBinder.createAndBindUi(this));
 }

Here, the binder instance, created using deferred binding, is told to bind the interface file elements to the UiField elements in this class. The return from this call is a VerticalPanel, which if you remember, is the root panel from our UI XML. If this was a standard Widget, we'd only be able to set an Element, however, because this is a Composite Widget, we're able to set a child widget using initWidget method.

NOTE: The name of the field in the class being bound to MUST be exactly the same as the ui:field entry, including case.

Now we have UI element bindings, we can treat this as if the UI had been created using the standard Java approach. Here, for example, are the setTitle and setImages methods :

 public void setTitle(String value) {
  title.setText(value);
 }
 
 public void setImages(GalleryImage[] images) {
  this.images = images;
  currentImageIndex = 0;
  displayImage();
 }
  
 private void displayImage() {
  image.setUrl(images[currentImageIndex].getUrl());
  image.setTitle(images[currentImageIndex].getCaption());
  caption.setText(images[currentImageIndex].getCaption());
 }

Adding Event Handlers

As it stands, our image gallery would simply display the first image in the array, what we need to do now is listen for Click events on the Prev and Next buttons in order to display other images.

In standard GWT we'd have to add anonymous ClickHandlers, but with the declarative interface we can use features of the generated UiBinder to do the work for us. For example, here's the click handlers for the buttons:

 @UiHandler("btnPrev")
 public void handlePrev(ClickEvent event) {
  if (currentImageIndex != 0) {
   currentImageIndex--;
   displayImage();
  }
 }

 @UiHandler("btnNext")
 public void handleNext(ClickEvent event) {
  if (currentImageIndex != images.length -1) {
   currentImageIndex++;
   displayImage();
  } 
 } 

In both cases, the UiHandler annotation tells GWT which UiField field this handler is for. The name of the method itself doesn't matter, it can be anything you like. In order to set the handler, GWT will look at the event and discover the name of the Handler class. It will then look for a method call add on the widget the event is being bound to. For example, if we had an event called MySimpleEvent that had an associated handler called MySimpleHandler, GWT would look for a method called addMySimpleHandler on the Widget specified in the UiHandler annotation.

A Quick Test

Before we go any further, it would be good to test this Widget. Here's an example of using the Widget, using photos from Flickr

public class UIBinderExample implements EntryPoint {

 private static final GalleryImage[] images = {
 new GalleryImage("http://farm4.static.flickr.com/3309/3622157565_fd079ac983.jpg","Bishop's Moat"),
 new GalleryImage("http://farm2.static.flickr.com/1257/928632149_71d88ac137.jpg","Family Of Goats"),
 new GalleryImage("http://farm1.static.flickr.com/61/193636096_1f34d7a78d.jpg","Wooden Boat - Sailing - Port Townsend")};
 
 public void onModuleLoad() {
  ImageGalleryWidget widget = new ImageGalleryWidget();
  widget.setImages(images);
  widget.setTitle("Sample Flickr Gallery");
    
  RootPanel.get().add(widget);
 }
}

Adding Style

At the moment the widget doesn't look very good; let's improve that by adding some CSS styles. To do this we first add a ui:Style element to our UI definition.

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' 
    xmlns:g='urn:import:com.google.gwt.user.client.ui'>

  <ui:style>
   .caption {font-weight:bold;width:100%}
   .button {color:red}
   .image {width:375px; height:500px}
  </ui:style>
  
  <!-- Rest Ignored -->
</ui:UiBinder>

We can then use those styles by setting the styleName property of the relevant elements, ie :

   <g:Cell>
    <g:Image styleName="{style.image}" ui:field="image"/>
 </g:Cell>

Reusing this Widget

GWT allows you to build up your UI using different definition files. What we'll do now is reuse this initial Widget in a new UI that is itself declared using XML. In order to do this we'll define a UI that uses two versions of this Image Gallery, and looks like so

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' 
    xmlns:g='urn:import:com.google.gwt.user.client.ui'
    xmlns:d='urn:import:com.maddison.client.widgets'>
    
 <g:HorizontalPanel spacing="5" width="100%">
  <g:Cell>
   <d:ImageGalleryWidget title="Gallery One" ui:field="galleryOne"/>
  </g:Cell>
  <g:Cell>
   <d:ImageGalleryWidget title="Gallery Two" ui:field="galleryTwo"/>
  </g:Cell>
 </g:HorizontalPanel>    
</ui:UiBinder>

The important part of this file is the urn:import:com.maddison.client.widgets namespace declaration. This states that widgets marked with the d namespace can be found in the com.maddison.client.widgets package. Properties on this Widget (for example the title) are set by calling a setXXX method on the given widget.

To show another feature of the declarive API, lets save this file as MainAppInterface.ui.xml. Our application will be defined in a Composite widget that looks like so :

public class MyApp extends Composite {
 @UiTemplate("MainAppInterface.ui.xml")
 interface MyAppUiBinder extends UiBinder<HorizontalPanel, MyApp> {}
 private static MyAppUiBinder uiBinder = GWT.create(MyAppUiBinder.class);

 private static final GalleryImage[] images = {
  new GalleryImage("http://farm4.static.flickr.com/3309/3622157565_fd079ac983.jpg","Bishop's Moat"),
  new GalleryImage("http://farm2.static.flickr.com/1257/928632149_71d88ac137.jpg","Family Of Goats"),
  new GalleryImage("http://farm1.static.flickr.com/61/193636096_1f34d7a78d.jpg","Wooden Boat - Sailing - Port Townsend")};
  
 
 @UiField ImageGalleryWidget galleryOne, galleryTwo;
 
 public MyApp() {
  initWidget(uiBinder.createAndBindUi(this));
  galleryOne.setImages(images);
  galleryTwo.setImages(images);
 }
}

You'll notice the UiTemplate annotation above the MyAppUiBinder interface. Normally GWT will look for a UI definition file that has the same name as the parent class, however, in this case we've told GWT that the interface file is actually called MainAppInterface.ui.xml by using the annotation.

Final Test

Our final application simply has to instantiate the MyApp interface like so:

public class UIBinderExample implements EntryPoint { 
 public void onModuleLoad() {
  RootPanel.get().add(new MyApp());
 }
}

Conclusion

Hopefully this post has shown how to use some features of the GWT declarative UI, by no means does it show everything that's possible!

A complete Eclipse project with all the code from this post can be found here

Wednesday, February 24, 2010

Using GWT 2 Custom Events

Introduction

In a previous post I showed how to create a custom GWT component based on GWT 1.7. In this post I'll show you how to perform the same thing using GWT 2's new event system. In order to make clear how custom GWT events are built, I'll be doing things slightly differently in that we'll be building it in a Model-Binder-View style.

The Model

The model is where we're going to concentrate on the majority of our effort as this is the component that will be generating the custom events. There's nothing special in the basic model class, it looks like this :

public class ListModel {
 final private List<ListItem> items = new ArrayList<ListItem>();

 public void addItem(ListItem item) {
  items.add(item);
 }
 
 public void removeItem(ListItem item) {
  items.remove(item);
 }
 
 public void removeAll() {
  items.clear();
 }
 
 public List getItems() {
  return Collections.unmodifiableList(items);
 }
}

Java Tip:Notice here that when we return the list of items, we wrap it in an UnmodifiableList. This makes the list immutable and thus stops any clients modifying the model state outside of our component.

The ListItem class looks like this:

public class ListItem {
 private final String text;
  
 public ListItem(String text) {
  this.text = text;
 }
 
 public String getText() {
  return text;
 }
  
        // Equals and HashCode hidden
}

In this example, ListItem is simply a wrapper around some text. We could use a string for the ListItem, but this method allows a user of the model to extend ListItem to include any extra required information (for example, adding a map of values).

Adding the HandlerManager

At this point our model isn't very reactive, a client would have to poll the model in order to see any changes. What we'll do now is fire an event when an item is added. In GWT 1.x this had to be done using listeners, however GWT 2 provides out of the box support for handling event registration and notification in the form of the com.google.gwt.event.shared.HandlerManager.

Adding the HandlerManager to our ListModel is straight forward, here's the HandlerManager added to the top of our class:

public class ListModel {
 final private HandlerManager handlerManager = new HandlerManager(this);
 final private List items = new ArrayList();
 
 // Other code hidden
} 

Notice that HandlerManager takes an object as it's constructor. The Object passed in is used as the source of all events this HandlerManager will fire.

The ItemAdded event

Events in GWT 2 come in two parts, a class that extends GWTEvent (the event object) and an interface that extends EventHandler (the handler interface). The event handler interface is the easiest to understand as EventHandler is simply a marker interface. The EventHandler for ItemAdded looks like so:

public interface ItemAddedHandler extends EventHandler {

 void onItemAdded(ItemAddedEvent event);
} 

The ItemAddedEvent class looks like so:

public class ItemAddedEvent extends GwtEvent<ItemAddedHandler> {
 private static final Type TYPE = new Type<ItemAddedHandler>();
 
 private final ListItem listItem;
 
 public ItemAddedEvent(ListItem listItem) {
  this.listItem = listItem;
 }
 
 public static Type getType() {
  return TYPE;
 }
 
 /** @returns The item added to the model */
 public ListItem getListItem() {
  return listItem;
 }
 
 @Override
 protected void dispatch(ItemAddedHandler handler) {
  handler.onItemAdded(this);
 }

 @Override
 public com.google.gwt.event.shared.GwtEvent.Type getAssociatedType() {
  return TYPE;
 }
}

The event object is slightly confusing because it fulfills two roles. On the one hand it's the object which the ListItem so that the handler can retrieve it when it's notified. On the other hand the event object also acts as the dispatcher for the given event.

Firing the event

Using these two new classes, when an item is added to our model, we can now fire the event. The following code shows the amended addItem method:

 public void addItem(ListItem item) {
  items.add(item);
  handlerManager.fireEvent(new ItemAddedEvent(item));
 }

When fireEvent is called the HandlerManager first calls setSource on the event object and sets it to the value passed into the constructor of the HandlerManager. It will then look for handlers registered against the given event and call them in the order they were registered in.

Registering an EventHandler

At the moment there's no way for a client to listen for the ItemAdded event. In order for this to happen we have to add an addItemAddedHandler to our ListModel class. This looks as follows:

public void addItemAddedHandler(ItemAddedHandler handler) {
      handlerManager.addHandler(ItemAddedEvent.getType(),handler);  
}

The Complete Model

Here's the complete ListModel code:

public class ListModel {
 private final HandlerManager handlerManager = new HandlerManager(this);
 private final List items = new ArrayList<ListItem>();

 public void addItem(ListItem item) {
  items.add(item);
  handlerManager.fireEvent(new ItemAddedEvent(item));
 }
 
 public void removeItem(ListItem item) {
  items.remove(item);
  handlerManager.fireEvent(new ItemRemovedEvent(item));
 }
 
 public void removeAll() {
  for (ListItem item : items) {
   handlerManager.fireEvent(new ItemRemovedEvent(item));  
  }
  
  items.clear();
 }
 
 public List getItems() {
  return Collections.unmodifiableList(items);
 }
 
 public void addItemAddedHandler(ItemAddedHandler handler) {
  handlerManager.addHandler(ItemAddedEvent.getType(),handler);  
 }
 
 public void addItemRemovedHandler(ItemRemovedHandler handler) {
  handlerManager.addHandler(ItemRemovedEvent.getType(),handler);
 }
}

From this you can see we've added events when an item is removed, and also fire the remove event when all the items are cleared. For completeness, the following show the ItemRemovedHandler and ItemEvent classes:

public interface ItemRemovedHandler extends EventHandler {

 void onItemRemoved(ItemRemovedEvent event);
}
public class ItemRemovedEvent extends GwtEvent<ItemRemovedHandler> {
 private static final Type<ItemRemovedHandler> TYPE = new Type<ItemRemovedHandler>();

 private final ListItem listItem;
 
 public ItemRemovedEvent(ListItem listItem) {
  this.listItem = listItem;
 }
 
 public static Type<ItemRemovedHandler> getType() {
  return TYPE;
 }
 
 public ListItem getListItem() {
  return listItem;
 }
 
 @Override
 protected void dispatch(ItemRemovedHandler handler) {
  handler.onItemRemoved(this);
 }

 @Override
 public com.google.gwt.event.shared.GwtEvent.Type<ItemRemovedHandler> getAssociatedType() {
  return TYPE;
 }
}

The List Component

The list component is very much simplified from the previous article, simply being a wrapper around either an LI or OL element:

public class ListComponent extends Widget {
 private static final String IDENTIFIER_PROPERTY = "IDENTIFIER"; 
 
 public enum ListType {
  ORDERED {
   protected Element createElement() {
    return Document.get().createOLElement();
   }
  },  
  UNORDERED {
   protected Element createElement() {
    return Document.get().createULElement();
   }
  };
  
  protected abstract Element createElement();
 }

 
 public ListComponent(ListType type) {
  setElement(type.createElement());
 }
 
 public void addItem(String label, Object identifier) {
  LIElement liElement = Document.get().createLIElement();
  liElement.setInnerText(label);
  liElement.setPropertyObject(IDENTIFIER_PROPERTY, identifier);
  
  getElement().appendChild(liElement);
 }
 
 public void removeItem(Object identifier) {
  Element childNode = getElement().getFirstChildElement();
  
  while (childNode != null) {
   if (identifier.equals(childNode.getPropertyObject(IDENTIFIER_PROPERTY))) {
    childNode.removeFromParent();
    break;
   }
   
   childNode = childNode.getNextSiblingElement();
  }
 }
}

As you can see here, an item consists of a label and an object identifier. The identifier is stored as an Object property in the new LI element so that during remove we can find the given element for a particular indentifier.

Binding the Model to the UI component

With the ListModel finished, we now need something that will register for events and modify a UI component when something is added. For this we'll create a binder which will update a UI list. It looks like this :

public class ListBinder {
 public ListBinder(final ListComponent list, ListModel listModel) {

  listModel.addItemAddedHandler(new ItemAddedHandler() {
   public void onItemAdded(ItemAddedEvent event) {
    ListItem listItem = event.getListItem();
    list.addItem(listItem.getLabel(), listItem);
   }
  });

  listModel.addItemRemovedHandler(new ItemRemovedHandler() {
   public void onItemRemoved(ItemRemovedEvent event) {
    list.removeItem(event.getListItem());
   }
  });
 }
}

The binder is very simple, in that it converts the events triggered by the model into UI actions. It's useful as it keeps a nice seperation of concerns.

A Quick Test

Finally we come to the fun part, actually testing this. For this I created a simple test client that adds a list item every second:

public class TestClient implements EntryPoint {

 public void onModuleLoad() {
  final ListModel model = new ListModel();
  final ListComponent list = new ListComponent(ListType.ORDERED);
  
  ListBinder binder = new ListBinder(list, model);
  
  Timer t = new Timer() {
   private int counter = 0;
   public void run() {
    model.addItem(new ListItem("New Item "+counter++));
   }
  };

  t.scheduleRepeating(1000);
  
  RootPanel.get().add(list);
 }
}

Conclusion

And there we have it, a simple introduction to creating and using a custom GWT 2 event. I could have gone on and extended the ListComponent to fire events when one of the elements are clicked, but that would have distracted from the main aim of this post.

An Eclipse project with all the code for this post can be found here.

Monday, September 21, 2009

Building Opera Unite Services in Java

For the last few weeks I've been experimenting with Opera Unite, due to be release in the next version of the Opera browser. Opera Unite services are built in JavaScript, however this felt like a limitation as building anything big in JavaScript alone can get a little hairy.

With this in mind I started on a few experiments to see if I could use GWT as a framework to build these services, thus allowing me to stay directly in the nice type safe world of Java.

GWT-Unite is the result of these experiments. It's a set of API's that allow easy creation of Opera Unite services without ever seeing a scrap of JavaScript! If your interested in taking a look, I've hosted it over at Google Code (gwt-unite.googlecode.com) where you'll find the source code, libaries, examples and documentation. If you have any ideas on how to make it better, why not join me!

Saturday, July 04, 2009

GWT Logging and JSNI

Logging is an essential component of any traditional Java environment, without it, tracking down issues would be time consuming. Unfortunately, on the browser, there's no standard place in which to output log messages. Sure, one solution could be to display a dialog box when something goes wrong, but normally you want to dsplay such things as debug messages which just won't work in a dialog solution.

As a solution to this most browsers provide some kind of logging console exposed through a JavaScript API. One of the best known, and possibly most widely used, is Firebug a JavaScript debug enviroment plugin for Firefox; others includeDragonFly for Opera and the new debug console for Internet Explorer 8. Whilst all these facilities are fantastic for direct JavaScript development, how do we access them from a GWT application?

Here I introduce my simple but effective GWT Logging Module that automatically detects the available browser logging system and connects to it. It was developed as a way of demonstrating GWT JSNI usage but developed into a framework which I use today.

If your too impatient are simply don't want to learn about JSNI, the full Logging module is available ready to use here and if your interested in the source, it's available as an Eclipse project here.

Using The Framework

Firstly the logging module needs to be added to your Eclipse build path, and then the following to your GWT module descriptor :

<inherits name="com.maddison.gwt.logging.Logging"/>

This single line will instantiate the Logging system when the application starts at which point you will see a "Logger Started" message displayed on whichever logging system your browser has installed. To access the Logger from your application simple use the following line :

private static final Logger LOG = Logging.getLogger();

All the logging methods of Logger are now available, for example :

private static final Logger LOG = Logging.getLogger();

public void doSomething() {
 LOG.info("Hello World");
}

The following logging systems are supported:

  • Opera -> DragonFly
  • Firefox -> Firebug
  • GWT hosted mode -> GWT console
  • IE8 -> Debug console
  • Chrome -> JavaScript console

Filtering Logging

A minimum logging level can be specified either as a URL parameter or as a meta tag parameter. The following shows example these:

....index.html?minLogLevel=WARN

or

<head>
 <meta name="minLogLevel" value="WARN"/>
</head>

In both the above examples only warning or higher severity messages will be logged. The severity level's are (most severe first) NONE, ERROR, WARN, INFO, DEBUG, ALL.

How It works

As mentioned in the introduction, this logging system was developed whilst building a JSNI tutorial. With this in mind lets take a look inside one of the Logging implementations, the Firebug logger.

In a standard JavaScript application the following code would log a warning to the Firebug logging console:

 console.warn(message);

Unfortunately, since Java is a typed language, this console object isn't available to us, however GWT provides a way around this in the form of JSNI methods. JSNI methods provide a way for us to write JavaScript directly into GWT classes. For example, the following shows the JSNI method for logging a Firebug warning :

private static native void firebugWarn(String message) /*-{
 console.warn(message);
}-*/;

As you can see, the method is marked as native and the body of the method is enclosed in the /*- and -*/ markers, the code between which will be copied to the compiled GWT application.

The isFirebugAvailable method is another place JSNI is used to good effect. In the logging system I've used the "Object Detection" pattern to determine the browser logging capabilities, here's how this is used in the Firebug logger:

public static boolean isAvailable() {
 return isFirebugAvailable() && BrowserUtils.getUserAgent().contains("mozilla");
}

private static native boolean isFirebugAvailable() /*-{
 if (typeof console != "undefined") {
  return true;
 } else {
  return false;
 }
}-*/;

Here we're checking to see if the console object is available to us (it won't be if Firebug isn't installed), and as an extra check we make sure we're running on Firefox

Deferred Binding

This logging framework makes decisions regarding which logger to use at runtime, however GWT offers another solution known as Deferred Binding. Deferred Binding allows the compiler to make decisions as to what to include in the final application at compile time. For example, if the framework was to use deferred binding, the GWT compiler would produce a separate application for each instance of the Logger, each version ONLY including the logger for the particular browser version. The bootstrap code would check the browser version and load the correct version of the compiled JavaScript. The idea is that the resulting Javascript is not only faster (because certain decisions don't have to be made at runtime), but also smaller.

This sounds great on paper, however in reality it does lead to longer compile times, and if there are any other parts of the application also using Deferred Binding it can lead to quite a few versions (known as permutations in GWT) of the application being created. For example, if there is another Deferred Binding flag that's either on or off, the GWT compiler will create "Number of Loggers" 6 x 2 = 12 versions of the application!

Deferred binding has it's place, however since all the loggers are small and only one decision has to be made when the application starts, I decided Deferred Binding just wasn't worth the payoff.

And that's it!

Originally this post had a step by step code walk through, however I later cut it down to just focus on JSNI. If your interested in seeing just how the framework works then please feel free to download the Eclipse project here. Just a quick note about the project; I don't use the GWT application creator but create GWT project by hand and instead of the project including the GWT libraries I use an Eclipse library (called "GWT") added to the project classpath to bring in the GWT libraries.

Friday, June 19, 2009

GWT and Google Visualization API - Tip

Google Visualization is an excellent API for adding graphing capabilities to any web application. Recently a GWT wrapper has been released which makes it easy to embed this API into GWT applications. The GWT module is really a wrapper around the standard Visualization JavaScript libraries and in order for everything to work the documentation says the following line is required in your GWT module:

<script source="http://www.google.com/jsapi"/>

With this line in place everything does indeed work, however I recently discovered a problem. Adding this line into the GWT module has the unfortunate side effect of the script element appearing in the GWT bootstrap code; the result of which is the browser will fetch the JSAPI library before actually loading your GWT module. Under normal circumstances, (ie when connected to the Internet), this isn't a problem, however this JavaScript fetch can cause significant delays if your using GWT hosted mode, or even offline, (only a small part of the application is concerned with graphing so if this library isn't loaded it's no big deal).

The Solution

The solution is not to add the script to the module definition, but instead to add it programmatically when the module is loaded. The following code shows how this issue was solved:

 public void onModuleLoad() {
  addGoogleJSAPIScript();
 }

 private void addGoogleJSAPIScript() {
       ScriptElement script = Document.get().createScriptElement();
       script.setPropertyString("language", "javascript");
       script.setPropertyString("src", "http://www.google.com/jsapi");
       Document.get().getElementsByTagName("head").getItem(0).appendChild(script);
 }

This code should be straight forward, all it's really doing is creating an HTML <script> element and setting the Google URL. Once this is added the browser fetches the JSAPI library, but the crucial thing is that it doesn't fetch the library in the boot strapper, but rather when the main UI module library has been loaded

Friday, January 30, 2009

GWT, Internet Explorer and XMLHttpRequest Caching

This morning I spent over an hour tracking down and solving a client/server communication issue which I'm going to document here, for all weary travellers who come this way. The application in question uses the GWT RequestBuilder in order to make an HTTP GET request to the server. When running in GWT Hosted mode I have a relay servlet that acts as a proxy allowing me to test the application against the real server without breaking the browser same origin policy.

The Problem

When running the application I couldn't understand why the first request retrieved the correct JSON response, but any further requests only ever returned this same original response, when in fact they should have been very different. I tried all the obvious things such as accessing the server using a browser and the server appeared to be working correctly.

I finally tracked the issue down to the fact that on Vista GWT hosted mode uses Internet Explorer as its embedded browser. Unfortunately due to some bugs (thanks to this post which gave me the required pointers), Internet Explorer will cache XMLHttpRequests if they're for the same URL. As it happens, because I'm using a relay servlet, all the requests do indeed look like they are going to the same URL, and thus IE keeps returning the same response, without ever sending the request to the server.

The Solution

The solution (at least when using hosted mode), is to change the Internet Explorer cache settings (I'm using IE 7), which can be done by selecting Tools, Options and clicking the Browser History settings button, (I'm not sure why cache settings are in browser history section!):

In the resulting dialog, chosing "Check for newer pages Every time I visit a page", resolved the issue. I would certainly recommend modifying this setting even if your not using XMLHttpRequests as I've also had issues with style sheets getting stuck in the IE cache!

Note: this appears to be a Windows only issue, on Linux GWT hosted mode uses Mozilla, although it certainly would be nice to choose either IE or Mozilla on windows!

Saturday, January 24, 2009

Quick Tip : Getting Eclipse to help spot common errors

Since Java is a statically typed language, the compiler is pretty good at spotting errors, but sometimes we do things that are syntactically correct, but which are semantically wrong; take for example the following code sample.

public class TestError {
  String personName;

  public TestError(String personName) {
       personName = persionName;
  }

  public int getNameSize() {
       return personName.length();
  }
}

The above code contains a common mistake, namely that the parameter personName is hiding the class field personName; all that's really happening is the parameter is getting re-assigned the value it originally had. The main problem with this kind of mistake is that the developer assumes the object state is full initialized after calling the constructor, but on calling the (admittely worlds most pointless) getNameSize() method a NullPointerException would be thrown.

There are a few ways that the above code could be corrected in order for the compiler to spot the error. One way is to set the personName class field to final, which tells the compiler the personName field MUST be assigned a value in the constructor, and thus ensures the object state is intialized correctly, i.e.:

public class TestError {
    final String personName;

    public TestError(String personName) {
  personName = personName;
    }

    public int getNameSize() {
  return personName.length();
    }
}

The compiler will now throw a "Blank field Person may not have been initialize" error and compilation will fail. This is good (and you should certainly make as many fields as you can final), but it doesn't help if we want to actually update the person name in a later method.

Another way we can give a hint to the compiler is to make the personName parameter final:

public class TestError {
    String personName;
    
    public TestError(final String personName) {
         personName = personName;
    }
    
    public int getNameSize() {
         return personName.length();
    }
}

Now the compiler won't let us modify the personName parameter and will throw a "The local field variable personName cannot be assigned" error, and again stop compilation. Setting parameters to final is probably a good idea, and a good way to state your intention to the compiler, but we probably don't want to do this on EVERY method.

Luckily Eclipse can come to our aid by spotting this, and other common potential issues. If we look at the original code in the Eclipse editor we see this:

Notice the yellow warning underline underneath the parameter assignment. Eclipse is giving us a warning that "The assignment to variable personName has no effect" (you can check this by hovering over the margin marker); That's pretty useful, but we tend to get use to, or just don't see, warnings. What we want to do is have Eclipse scream at us here's a mistake and halt compilation; fortunately for this blog post, this can be done.

The trick lies in the depths of the Eclipse preferences under the Java section. The following image shows the full path:

In the resulting dialogue on the right hand side you'll see several sub-options, but the one we're interested in is the Potential programming problems; when expanded it looks as follows:

By default this dialogue has all the options set to warning or ignore, which results in Eclipse waving pathetically at us rather than screaming. The option that would have protected our original code is Assignment has no effect (eg 'x = x'):. If we set this to error, Eclipse will now halt all compilation until it's fixed; our original code now looks like this in the editor :

We've now found the error at compilation, rather than during testing, when it could be much harder to track down. There are lots more options within the potential programming problems section and I encourage you to take a look and set the relevant ones; you can find more information about each one by pressing F1 in the dialogue and reading the Eclipse help.

Warning

These Eclipse compiler options are indeed a great help but PLEASE don't use them as a short-cut to writing good defensive code! In the given example above, the best way to write the code is to make the personName field final which not only protects against the object being set up correctly, it also tells future developers the intent of the personName field.