4

I found the need to use String.format in my project. However, this doesn't work in GWT, and I have a replacement that uses GWT RegExp. However, I would like my project to run without errors when using the normal Swing interface that doesn't depend on GWT. The shared code depends on the String.format though. The problem is that I don't know how to make the GWT compiler use a different class than the other code. I already tried doing it all in one file, but it doesn't work, since GWT can't handle the NoClassDefFoundError exception that I use to detect when GWT is missing from classpath.

Here is my current code:

package testpackage.shared;

import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.regexp.shared.SplitResult;

public class Util {

  public static String format(final String format, final Object... args) {
    try {
      final RegExp regex = RegExp.compile("%[a-z]");
      final SplitResult split = regex.split(format);
      final StringBuffer msg = new StringBuffer();
      for (int pos = 0; pos < split.length() - 1; pos += 1) {
        msg.append(split.get(pos));
        msg.append(args[pos].toString());
      }
      msg.append(split.get(split.length() - 1));
      return msg.toString();
    } catch (NoClassDefFoundError ex)  {
      return String.format(format, args);
    }
  }
}

How do I make this compile and run on GWT and the JRE without GWT in classpath? Do I really need to make the Ant build script replace the whole file with a different one when building for GWT versus Swing/Sun JRE?

Janus Troelsen
  • 20,267
  • 14
  • 135
  • 196

1 Answers1

5

One solution is to use Deferred Binding Replacement:

<replace-with class="testpackage.shared.UtilGWT">
  <when-type-is class="testpackage.shared.Util"/>
</replace-with>

And then call GWT.create(Util.class) in your GWT code. To avoid the Swing project picking up the UtilGWT class, I would put it into a different source folder (or maybe instruct the javac task of Ant to ignore the file).

However, this still won't allow you to reuse the part of the code which calls GWT.create() in your Swing application. So you'd have to create a factory, or call some initialization when the application starts, or something like that... all the usual problems if you're living without Dependency Injection.

If you want to use Dependency Injection (e.g. with Guice/Gin), the whole process of substituting an implementation becomes very natural: Create an abstract Util class/interface, and two implementations: UtilGWT and UtilJRE - then set up the correct instance in your module (you'd have a different module for your GWT and Swing applications), and you automatically get the correct implementation everywhere you need it.

Chris Lercher
  • 37,264
  • 20
  • 99
  • 131