In a recent post, I’ve demonstrated how one can use the same domain-specific (Model) classes end-to-end, from the Mobile layer, to the GWT Front-End, up to server-side and Persistence layer (JPA).

Recently, I’ve done a serious refactoring of my Android Receipts mobile app, using java.net.URIs to keep track of the receipts’ images location in the (local) filesystem on the mobile: whilst these are not used at all (and, in fact, have no meaning) on the GWT front-end (although, may “regain” semantics on the server side, where may be needed to track the location of the persisted images) they cause a bit of confusion, as the java.net.URI class is not supported by GWT.

What I then decided to do, was to find out how one could overcome such a problem, and here is what I found.

The key part in replacing a JRE class that GWT does not support is in using <super-source> that does a virtual `chroot` on the directory structure:

# GwtPlayground/lib/src/com/alertavert/receiptscan/URI.gwt.xml
<module rename-to='ReceiptscanURI'>
<inherits name='com.google.gwt.user.User'/>
<!-- Specify the paths for translatable code, by redefining the super-source
so that the class under jre/java/net/URI will be correctly identified by the
compiler as java.net.URI
-->
<super-source path='jre'/>
</module>

The URI.java file goes under jre/java/net/ – the GWT compiler will take care of the rest.
Remember that in URI.java the package is java.net:

# com/alertavert/receiptscan/jre/java/net/URI.java

// Copyright AlertAvert.com (c) 2011. All rights reserved.
// Created Jan 14, 2011, by M. Massenzio (marco@alertavert.com)

package java.net;

/**
* Horrible hack to support Receipt's use of java.net.URI location for the
* actual image file, which is however not supported in GWT code
*/
public interface URI {
public abstract String getPath();
}

This must be “kept hidden” from Eclipse, or it will flag it as a compilation error (the folder structure and the package declartion won’t match).

The GWT compiler only needs access to the source files (and, as far as URI.java is concerned, that’s all that’s needed too).
However, both Eclipse and the actual server-side code will need access to the model classes (eg, Receipt.java) and also you want them someplace where it’s easy to edit them, and the updates be reflected reasonably quickly in the compiled code (as well as in the running web app).

Keep them in a `linked folder` in your GWT project (to the Android project, where they belong) and add as well a symlink to the source folder:

$ ls -lad src/com/alertavert/receiptscan/model
lrwxrwxrwx src/com/alertavert/receiptscan/model ->
/workspaces/main/polaris/common/com/alertavert/receiptscan/model

Here, you can place the ReceiptscanModel module:

# GwtPlayground/lib/src/com/alertavert/receiptscan/ReceiptscanModel.gwt.xml
<module rename-to='ReceiptscanModel'>
<inherits name='com.google.gwt.user.User'/>

<!-- Mock implementation of java.net.URI which GWT does not support, and
in fact, is not necessary server-side, but Receipts declares and would break
GWT compilation.
This enables the GWT module to compile, and will never be used at runtime.
-->
<inherits name='com.alertavert.receiptscan.URI'/>

<!-- No need to specify the entry point class or anything else -->
<!-- for that matter: this is only needed so that classes in -->
<!-- the .model folder will be incluse in the transitive closure -->
<!-- of GWT compiler. -->
<!-- Specify the paths for translatable code -->
<source path='model'/>
</module>

Last step, is to create a JAR that the GWT compiler will use (needs to be in the classpath of the GWT Eclipse project):

#!/bin/bash
#
# GwtPlayground/lib/create-jar.sh
#
# Simple script to create JAR file containing the java.net.URI replacement for GWT
# Uses the -C option to descend into the src/ dir before packaging the files.

USAGE="Please enter a version number for the JAR (eg, 1.0)"

if [ -z $1 ]; then
echo $USAGE
exit -1;
fi

echo "Creating jar file receiptscan_gwt_model_$1.jar"
jar -cvf receiptscan_gwt_model_$1.jar -C src com >/dev/null 2>&1

Note that every time you edit any of the Java files in the `model` package, the server will need to be restarted (there is a button in Eclipse’s GWT Development console that allows you to quickly do so) and the create-jar.sh needs to be re-run, so that the new code is made accessible to the GWT compiler.

Leave a comment

Trending