Emulate JRE class in GWT

In our recent code search, we found that some GWT client code is used  in one of the classes in GWT shared package.

The GWT client classes used are “com.google.gwt.i18n.client.NumberFormat” and “com.google.gwt.i18n.client.DateTimeFormat“. This would cause problem if the class is used in server side since there is no GWT client dependency in server side.

On the other hand, we know JRE also has its own number format and date formate, however we all know that GWT’s implementation of the Java API’s are incomplete, and that using types that Google hasn’t provided as translatable will result in a GWT compiler error. As a result, we can not use the “java.text.DecimalFormat” and “java.text.SimpleDateFormat” neither.   This creates a dilemma for us that neither JRE’s nor GWT’s implementation can be used in our shared class.

To solve this problem. we can create a SharedXXXFormat and then an empty client side stub for the server version that is never used. Take date format for example:

import java.text.SimpleDateFormat;
import java.util.Date;

import com.google.gwt.core.shared.GWT;
import com.google.gwt.i18n.client.DateTimeFormat;

/**
 * Created with IntelliJ IDEA.
 * Date: 12/20/13
 */
public class SharedDateFormat
{
    private String pattern;

    public SharedDateFormat(String pattern)
    {
        this.pattern = pattern;
    }

    public String format(Date date)
    {
        if(GWT.isClient())
        {
            return DateTimeFormat.getFormat(pattern).format(date);
        } else {
            return new SimpleDateFormat(pattern).format(date);
        }
    }
}

DO remember to use the “GWT” from shared package rather than client package.

Then create a client stub out of the java.text.SimpleDateFormat in the super source.

package java.text;

import java.util.Date;

/**
 * this class is here to make the gwt compiler happy since we use un-emulated jre classes in the shared
 */
public class SimpleDateFormat
{
    public SimpleDateFormat(String pattern) {}
    public String format(Date date) {return null;}
}

Finally, don’t forget to add your super-source tag to your *.gwt.xml:

<super-source path=”clientStubs”/>

 

More about super source tag:

Overriding one package implementation with another

The <super-source> tag instructs the compiler to “re-root” a source path. This is useful for cases where you want to be re-use an existing Java API for a GWT project, but the original source is not available or not translatable. A common reason for this is to emulate part of the JRE not implemented by GWT.

For example, suppose you want implement the UUID class provided by the JRE under java.util. Assume your project’s module file iscom/example/myproject/MyProject.gwt.xml. Place the source for the UUID class intocom/example/myproject/jre/java/util/UUID.java. Then add a line to MyProject.gwt.xml:

    <super-source path="jre" />

This tells the compiler to add all subfolders of com/example/myproject/jre/ to the source path, but to strip off the path prefix up to and including jre. As a result,com/google/myproject/gwt/jre/java/util/UUID.java will be visible to the compiler asjava/util/UUID.java, which is the intended result.

The GWT project uses this technique internally for the JRE emulation classes provided with GWT. One caveat specific to overriding JRE classes in this way is that they will never actually be used in development mode. In development mode, the native JRE classes always supercede classes compiled from source.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s