Archive

Archive for August, 2009

GWT 2.0 first stab at RunAsync

August 31st, 2009 Chris Hane 7 comments

With the new GWT 2.0 (due to be released this year?), they have add a couple of great features. The one I’m most excited about from a users perspective is RunAsync (aka code splitting). To quickly recap, this feature will split a GWT application into multiple developer controlled (split points) downloaded files. We are reworking our internal GUI architecture and have decided to use the unreleased GWT version for development. Our largest application before compression (with obfuscation) is weighing in around 1.4MB. That’s pretty hefty for downloaded javascript files.

We have limped along waiting for GWT 2.0 and code splitting. We didn’t want to put in a temporary solution of using URL redirects and manually splitting our code into modules for a 6 month solution. We’re happy we didn’t. With our refactoring effort, we have designed it so that we can easily have split points at our “module” level (basically a group of related screens).

We don’t have hard numbers yet for an apples-apples comparison, we like our first attempt. It looks like we will have three downloads to start our application. The first bundle is about 140K, the second which is a module is about 80K and a leftover module which is 500K.  The leftover module is primarly framework items (both GWT – e.g., Button, and our internal framework code).

We expect, as we work with the new functionality, to be able to get these values to go down (particularly the third – leftover download).  After all, we only have one split point right now.  We also are probably going to put in a new “home” page that displays when the user (same for every user) logs in so that the other download bundles can be download in the background.

The trick with RunAsync is to get the use case correct.  RunAsync as it’s name implies doesn’t execute code sequentially.  Therefore we had to add a callback mechanism into our code to display the GUI that was just downloaded.

For those interested it looks something like:

public void retrieveViaCallback(final OurInternalCallBackGuiObject callback){
      GWT.runAsync(new RunAsyncCallback(){
         public void onFailure(Throwable err){
            Window.alert("code download failure");
         }
 
         public void onSuccess(){
            callback.show();
         }
      });
   }

We haven’t dealt with error handling yet (hence the call to Window.alert); but the RunAsync is pretty easy to get going if you have good modularization in your code base already.

 
Categories: Gwt, Java

How to Intercept GWT Events…

August 28th, 2009 Chris Hane 2 comments

In reality it can’t be done with the stock code. In our application we would like to be able to “stop” an event from being fired further.

One example, we have three event handlers that can be added A, B, C (validation, required check, and save rpc). We add the handlers to a button in that order when needed (sub class determine which handlers to add). We want to be able to specify in A or B handler that the event should stop propagating to other handlers.

We tried a couple of different things (including starting to add our own event handling logic) and we settled on two changes to GWT itself. We added a method to GWTEvent:
- public void stop(); /* record that the event should not be passed to more handlers */
- public void isStopped(); /* is the event stopped for further processing */
- public void unStop(); /* reset the stop flag to be false – did in case event is reused */

In our event handlers we can now call event.stop() to stop further propagation.

In HandlerManager.HandlerRegister we modified

private <H extends EventHandler> void fireEvent(GwtEvent<H> event,
        boolean isReverseOrder) {
      Type<H> type = event.getAssociatedType();
      int count = getHandlerCount(type);
      if (isReverseOrder) {
        for (int i = count - 1; i >= 0; i--) {
          H handler = this.<H> getHandler(type, i);
          event.dispatch(handler);
          if(event.isStopped()) { // CUSTOM: event stop processing
            event.unStop(); // did this in case events are reused
            break;
          }
        }
      } else {
        for (int i = 0; i < count; i++) {
          H handler = this.<H> getHandler(type, i);
          event.dispatch(handler);
          if(event.isStopped()) { // CUSTOM: event stop processing
            event.unStop(); // did this in case events are reused
            break;
          }
        }
      }
    }

While this is a very specific use case, hopefully with enough examples, some thought will be put into an extension mechanism for HandlerManager. Until then, we get to live with our solution.

EDIT: After a post on the GWT list, it looks like this type of use case (developer extensions for the event handling) where considered but deemed too much/too varied to include anything in the GWT 2.0 timeframe. Here is the discussion.

 
Categories: Gwt, Java

Gradle, GWT, Logging Compile Errors

August 11th, 2009 Chris Hane 3 comments

We have been using the gradle build system for some time (0.7 right now). In the process of updating some of our infrastructure pieces I decided to make the GWT compile process a bit more robust and include it in the gradle build (much more so than we had been doing).  For the most part it is a very straight forward process.  This blog by Trond Andersen lays out just about everything you need to know (I’ve posted it below with a few modifications just in case it disappears).

My biggest problem came when I tried to execute the compile and nothing happened.  Actually, the console returned a Java System exit error of 1.  Not very helpful.  I tried a bunch of stuff to figure out what I was missing. Turns out logging anything from a forked process is a bit more difficult than not. And then gwt compiler uses a non standard logging mechanism.  I finally found the option to pass to the compiler:  -treeLogger

If you are having issues with your compile, this is a great parameter to know about.  It will popup a new window with the error messages in a tree format – very nice.  This works even when the compile process is run as a seperate jvm – which is key if you want to set the classpath. Turns out I was missing classpath entries which is a two second fix to add to the gwt dependency chain in gradle (see below).

Anyway, here is a modified version of the process with the treeLogger inserted but commented out:

usePlugin('war')
 
//cut standard war build file configuration
 
gwtBuildDir = 'some/path/to/an/output/directory/for/gwt/javascript'
 
task gwtCompile << {
  created = (new File(gwtBuildDir)).mkdirs()
  ant.java(classname:'com.google.gwt.dev.Compiler',
              failOnError: 'true',
              fork: 'true') {
    jvmarg(value: '-Xmx184M')
    arg(line: '-war ' + gwtBuildDir)
    arg(line: '-logLevel INFO')
    arg(line: '-style PRETTY')
//    arg(line: '-treeLogger')
    arg(value: 'me.trond.app.MyApp')
    classpath {
      pathElement(location: srcRootName + '/' + srcDirNames[0])
      pathElement(path: configurations.gwt.asPath)
    }
  }
}
 
Add a configuration type just for the gwt classpath:
 
configurations {
  gwt
}
 
This also had to be reflected in the dependencies:
 
dependencies {
//  ...
  gwt name: 'gwt-user', version: '1.6.4'
  gwt name: 'gwt-dev-windows', version: '1.6.4'
// ... other dependencies
}
 
Make sure the gwtCompile task is called before packaging up the war file:
 
war.dependsOn gwtCompile
 
Also ensured that the result of the gwtCompile is included in the war file:
 
war {
  //Adds the JavaScript and resources compiled by the GWT compiler
  fileSet(dir: file(gwtBuildDir) )
}
 
Categories: Gwt, Java

Rooting out Exceptions in GWT

August 4th, 2009 Chris Hane No comments

I have a case where my gwt app loads in the client browser, performs an RPC call, receives the results and then stops.  I have no clue as to why.  Debuging on firebug and after the result (which show in the net panel and the script panel (firebug 1.4.0)) is returned, nothing is executed.  There are no errors, and breakpoints are never tripped.

I am building a special debug version now and there is a way to add a generic exception handler. I had used this before and forgotten about it until someone pointed it out to me again.

A quick example…

//chain handlers
private UncaughtExceptionHandler ueh;
 
ueh = GWT.getUncaughtExceptionHandler();
GWT.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
  public void onUncaughtException(Throwable t) {
    logToConsole("AppController: Uncaught exception handled: " + t.getMessage());
    if (ueh != null) {
      ueh.onUncaughtException(t);
    }
  }
});
 
Categories: Gwt, Java