GWT Generator Experiments – 2

August 30th, 2008 Alex Moffat Posted in GWT | 1 Comment »

The example code in the previous post didn’t actually generate any code. This one shows how to generate code to produce an implementation for an interface that is the argument to the GWT.create(...) method. To recap, the example code whose compilation is going to invoke the generator looks like

public class Main implements EntryPoint { private GenerateExample example = GWT.create(GenerateExample.class); public void onModuleLoad() { Window.alert(example.getText()); } }

with GenerateExample defined as

public interface GenerateExample extends GenerateMe { public String getText(); }


To output the generated Java code you use a PrintWriter obtained from the GeneratorContext using the tryCreate method. This takes as arguments the names of the package and the class for the generated code. The example below is going to generate the same Java every time it is called, there is no variation for different property values, so the name of the generated class is simply constructed from the name of the interface passed to the GWT.create(...) method. Of course the name passed to tryCreate(...) must be the name returned from the generate(...) method

String packageName = classType.getPackage().getName(); String className = classType.getName() + "Impl"; PrintWriter pw = ctx.tryCreate(logger, packageName, className); // Output the Java code return packageName + "." + className;

If there is already a type defined with the provided name then tryCreate returns a null, otherwise a PrintWriter is returned. This means you don’t have to implement any sort of caching system if you are going to generate the same code for multiple calls to the generator.

To make it slightly easier to output Java code to the PrintWriter GWT provides the ClassSourceFileComposerFactory and SourceWriter. These provide useful methods for handling imports, indenting the generated code etc.

If we require that GenerateExample defines a single method public String getText() then the simplest possible implementation for the code generation in the ExampleGenerator would be.

if (pw != null) { System.out.println("tryCreate returned a PrintWriter"); ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(packageName, className); factory.addImplementedInterface(classType.getQualifiedSourceName()); SourceWriter sw = factory.createSourceWriter(ctx, pw); sw.indent(); sw.println("public String getText() { return \"Hello World\"; }"); sw.commit(logger); } else { System.out.println("tryCreate returned null"); }

The first few lines of output when compiling Main using the ExampleGenerator are shown below.

CompileGWTModule: [java] Compiling module com.lombardi.gwtexample.generatoruser.GeneratorUser [java] classType interface com.lombardi.gwtexample.generatoruser.client.GenerateExample [java] user.agent gecko [java] tryCreate returned a PrintWriter [java] classType interface com.lombardi.gwtexample.generatoruser.client.GenerateExample [java] user.agent gecko1_8 [java] tryCreate returned null [java] classType interface com.lombardi.gwtexample.generatoruser.client.GenerateExample [java] user.agent ie6 [java] tryCreate returned null

As you can see a PrintWriter is only created for the first invocation of tryCreate. Instead of returning “Hello World” for all values of user.agent I modifed the code to generate a different message for each user.agent property value. This requires a different className for each user.agent value as well.

String className = classType.getName() + "Impl_" + userAgent; 

sw.print("public String getText() { return \"Hello World from "); sw.print(userAgent); sw.println("\"; }"); 

Using this generator compilation produces different output with a PrintWriter returned for each different user.agent value.

CompileGWTModule: [java] Compiling module com.lombardi.gwtexample.generatoruser.GeneratorUser [java] classType interface com.lombardi.gwtexample.generatoruser.client.GenerateExample [java] user.agent gecko [java] tryCreate returned a PrintWriter [java] classType interface com.lombardi.gwtexample.generatoruser.client.GenerateExample [java] user.agent gecko1_8 [java] tryCreate returned a PrintWriter [java] classType interface com.lombardi.gwtexample.generatoruser.client.GenerateExample [java] user.agent ie6 [java] tryCreate returned a PrintWriter

The code is generated into the location specified by the argument to the -gen parameter of the GWTCompiler. Here’s what is generated for IE6.

package com.lombardi.gwtexample.generatoruser.client; public class GenerateExampleImpl_ie6 implements com.lombardi.gwtexample.generatoruser.client.GenerateExample { public String getText() { return "Hello World from ie6"; } }

One Response to “GWT Generator Experiments – 2”

  1. [...] GWT Generator Experiments – 2 Alex Moffat continues his excellent series discussing GWT Generators. [...]

Leave a Reply