Petr Kozelka

GWT MVP: supporting legacy URL tokens

21 January 2011 -

Recently I started to migrate a GWT application to MVP, in order to learn it, and also to enjoy the promised advantages.
For now I decided to use the MVP framework that comes with GWT 2.1. Migration itself was relatively easy, but the framework dictates how the token is structured - and it is quite simple:

PLACEPREFIX + “:” + PARAMS

The colon is hardcoded in the AbstractPlaceHistoryMapper class, but my previous implementation uses slash (and a slightly different approach to select the view).
The application is integrated with few other systems via URLs, and naturally I need to support my original syntax, in addition to the one required by the framework.
The simplest way seems to be, trapping the occurrences of original syntax, and translate it into the new one.
Fortunately, it is quite simple. The class PlaceHistoryMapper (from GWT) works with history strictly via Historian interface, with a default implementation that uses History api. So, I derived my own historian from that implementation and reimplemented it accordingly:

MyHistorian.java

public class MyHistorian extends PlaceHistoryHandler.DefaultHistorian {
  public String getToken() {
    String token = super.getToken();
    if (token == null) {
      return null;
    }
    if (token.startsWith("oldprefix/")) {
      token = "NewPlacePrefix:" + token.substring(10);
    }
    return token;
  }
}

As you see, the implementation is really simple. In many cases, the translation logic will be far more complex, but this shows the idea.
Now we also need to make GWT use our implementation instead of the default one. This can be achieved via GWT’s Deferred Binding, because PlaceHistoryHandler creates historians with GWT.create() call.

MyApp.gwt.xml

This is a fragment you should add to your .gwt.xml file:

...
    <replace-with class="net.kozelka.myapp.client.MyHistorian">
      <when-type-is class="com.google.gwt.place.shared.PlaceHistoryHandler.DefaultHistorian"/>
    </replace-with>
...

Note that this approach works for me with GWT 2.1.1 - I did not check any previous versions.
If you have any ideas how to do this in a better way, please share it here.

Further hints

  • keep the translation logic in a separate class
  • to get feedback on bad urls:
    1. create also MyDebugHistorian which makes something annoying (like Window.alert) when legacy syntax is detected
    2. bind it in your MyAppDebug.gwt.xml module descriptor, instead of the “silent” implementation
  • use some logging mechanism - to record uses of old syntax even in production code

References

Fork me on GitHub
Fork me on GitHub