Skip to Content »

Tech Life of Recht » Getting started with GWT (the manual way)

 Getting started with GWT (the manual way)

  • August 14th, 2006
  • 10:27 pm

I thought a small tutorial on how to get started with Google Web Toolkit might be in order. The GWT package contains some utilities, but I have found that in order to actually deploy to a Tomcat, you need to do quite a bit of stuff yourself.

This tutorial is based on GWT 1.1.0, Eclipse, Tomcat and Ant. It's assumed that Tomcat is installed somewhere (simply download and unzip/untar, and you're ready to go).

Creating a project

Create a new project in Eclipse - just a regular Java project. Make sure you use separate source and build folders.

Create the following dirs:
lib
lib/build
lib/core

Copy gwt-dev-*.jar and gwt-user.jar from GWT to lib/build.
Download ant-gwt-1.1.0.jar, xdoclet-gwt-module-0.1, gwt-xdoclet-1.2.3.jar, and xjavadoc-1.1.jar and place them in lib/build.

Place gwt-servlet.jar from GWT in lib/core together with any 3rd party libs you're using.

Add all jars (both in lib/build and lib/core) to the Eclipse build path (Right click on a jar and select Build path->Add to build path).

Create the following packages in Eclipse:
dk.contix.gwt
dk.contix.gwt.client
dk.contix.gwt.shared
dk.contix.gwt.service

In the dk.contix.gwt package, create a new dir called "public" and create a new HTML file:

CODE:
  1. <html>
  2.   <head>
  3.     <title>Name of module</title>
  4.     <meta name="gwt:module" content="dk.contix.gwt.Module">
  5.     <link rel="stylesheet" type="text/css" href="style.css">
  6.   </head>
  7.   <body>
  8.     <script type="text/javascript" src="gwt.js"></script>
  9.   </body>
  10. </html>

The file should be called Module.html in this example.

Setting up build

To actually compile and deploy, you need a ant build.xml file. Use this file:

CODE:
  1. <?xml version="1.0"?>
  2. <project default="compile" name="Module" basedir=".">
  3.   <property file="build.properties"/>
  4.  
  5.   <path id="classpath">
  6.     <pathelement location="src"/>
  7.     <pathelement location="target/classes"/>
  8.     <fileset dir="lib">
  9.       <include name="**/*.jar"/>
  10.     </fileset>
  11.   </path>
  12.  
  13.   <path id="sourcepath">
  14.     <pathelement location="src"/>
  15.   </path>
  16.  
  17.   <target name="init">
  18.     <tstamp/>
  19.     <mkdir dir="target"/>
  20.     <mkdir dir="target/classes"/>
  21.     <mkdir dir="target/web"/>
  22.   </target>
  23.  
  24.   <target name="clean">
  25.     <delete dir="target"/>
  26.   </target>
  27.  
  28.   <target name="compile" depends="init,generate">
  29.     <javac classpathref="classpath" destdir="target/classes" debug="true">
  30.       <src refid="sourcepath"/>
  31.     </javac>
  32.  
  33.     <taskdef resource="dk/contix/ant/gwt/ant-gwt.xml" classpathref="classpath" />
  34.     <gwtcompile destdir="target/web" optimize="true">
  35.       <fileset dir="src">
  36.         <include name="**/*.gwt.xml"/>
  37.       </fileset>
  38.     </gwtcompile>
  39.  
  40.     <copy todir="target/classes">
  41.       <fileset dir="src">
  42.         <exclude name="**/*.java"/>
  43.       </fileset>
  44.     </copy>
  45.   </target>
  46.  
  47.   <target name="generate">
  48.     <taskdef resource="xdoclet/modules/gwt/doclet.xml" classpathref="classpath"/>
  49.     <gwtdoclet destdir="src">
  50.       <fileset dir="src">
  51.         <include name="**/*.java"/>
  52.       </fileset>
  53.       <interface/>
  54.       <async/>
  55.       <module/>
  56.       <servicefactory class="dk.contix.gwt.client.ServiceFactory"/>
  57.       <webxml output="../target/web.xml"/>
  58.     </gwtdoclet>
  59.   </target>
  60.  
  61.   <target name="deploy" depends="compile">
  62.     <fail unless="deploy.root" message="You need to define deploy.root in build.properties"/>
  63.  
  64.     <mkdir dir="${deploy.root}"/>
  65.     <mkdir dir="${deploy.root}/WEB-INF"/>
  66.     <mkdir dir="${deploy.root}/WEB-INF/classes"/>
  67.     <mkdir dir="${deploy.root}/WEB-INF/lib"/>
  68.  
  69.     <copy todir="${deploy.root}">
  70.       <fileset dir="target/web"/>
  71.     </copy>
  72.     <copy todir="${deploy.root}/WEB-INF/classes">
  73.       <fileset dir="target/classes"/>
  74.     </copy>
  75.     <copy todir="${deploy.root}/WEB-INF/lib">
  76.       <fileset dir="lib/core">
  77.         <include name="**/*.jar"/>
  78.       </fileset>
  79.     </copy>
  80.     <copy file="target/web.xml" todir="${deploy.root}/WEB-INF"/>
  81.   </target>
  82. </project>

Creating a launcher

If you want to be able to run the application in hosted mode, you need a launcher. Use this for the purpose - put the following in launch.sh and run chmod +x launch.sh (replace GWT_HOME with the real path to GWT):

CODE:
  1. #!/bin/sh
  2. APPDIR=`dirname $0`
  3. GWT_HOME=/pack/gwt-linux-1.1.0
  4. CLASSPATH="$GWT_HOME/gwt-user.jar:$GWT_HOME/gwt-dev-linux.jar"
  5. for i in `find . -name '*.jar'`; do
  6.   CLASSPATH="$CLASSPATH:$i"
  7. done
  8. CLASSPATH="$CLASSPATH:bin"
  9. export CLASSPATH
  10.  
  11. MODULE=$1
  12. shitf
  13.  
  14. java com.google.gwt.dev.GWTShell -out $APPDIR/www "$@" $MODULE/${MODULE/*./}.html

When you actually have some code, you can run "./launch.sh dk.contix.gwt.Module" to start the application in hosted mode.

Adding some code

Now it's time to add some code. Start with the entry point class, which should be called Module in thie example:

CODE:
  1. package dk.contix.gwt.client.Module;
  2.  
  3. import com.google.gwt.core.client.EntryPoint;
  4. import com.google.gwt.user.client.ui.*;
  5.  
  6. /**
  7. * Class description here.
  8. *
  9. * @gwt.module package="dk.contix.gwt" include="shared,client"
  10. */
  11. public class Module implements EntryPoint {
  12.   public void onModuleLoad() {
  13.     final HorizontalPanel p = new HorizontalPanel();
  14.  
  15.     Hyperlink link = new Hyperlink();
  16.     link.setText("Press me");
  17.     link.addClickListener(new ClickListener() {
  18.       public void onClick(Widget sender) {
  19.       }
  20.     }
  21.     p.add(link);
  22.     RootPanel.get().add(p);
  23.   }
  24. }

Deploying

At this point, you should actually be able to compile and deploy this very simple application. First you have to create build.properties in the project root and specify where the application should be deployed, for example

CODE:
  1. deploy.root=/pack/apache-tomcat-5.5.15/webapps/gwt

Then just execute the following:
ant deploy

And start tomcat. At this point, you should be able to access http://localhost:8080/gwt/dk.contix.gwt.Module/Module.html and see a link on a page. Pressing the link shouldn't do anything.

Adding a service

Now we want to implement a service and call it by clicking the link. First, define the new service:

CODE:
  1. package dk.contix.gwt.service;
  2.  
  3. /**
  4. * Simple service implementation.
  5. * @gwt.interface service="dk.contix.gwt.shared.ModuleService" path="/moduleService"
  6. */
  7. public class ModuleServiceImpl extends RemoteServiceServlet {
  8.  
  9.   /**
  10.    * @gwt.serviceMethod
  11.    */
  12.   public String getDoubleText(String text) {
  13.     return text + text;
  14.   }
  15. }

The service class should actually implement an interface, but we're going to generate it automaticaly. Do so by executing

CODE:
  1. ant generate

and refresh the project in Eclipse. At this point, dk.contix.gwt.shared should contain two new interfaces, ModuleService and ModuleServiceAsync. Also, a service factory has been created in dk.contix.gwt.client.
Modify the ModuleServiceImpl class so it implements ModuleService:

CODE:
  1. public class ModuleServiceImpl extends RemoteServiceServlet implements ModuleService {

Calling services

At this point, we're ready to call the remote service from the client. Modify the ClickListener:

CODE:
  1. Hyperlink link = new Hyperlink();
  2.     link.setText("Press me");
  3.     link.addClickListener(new ClickListener() {
  4.       public void onClick(Widget sender) {
  5.         ServiceFactory.getModuleService().getDoubleText("testing1", new AsyncCallback() {
  6.           public void onFailure(Throwable caught) {
  7.             p.add(new Label("Error: " + caught.toString()));
  8.           }
  9.  
  10.           public void onSuccess(Object result) {
  11.             String t = (String)result;
  12.             p.add(new Label("Result: " + t));
  13.           }
  14.         });
  15.       }
  16.     }

Deploy the application again. Deploying will automatically generate a new web.xml with a servlet mapping the new service. After restarting Tomcat, you should be able to click the link and get a result back.

That's it

Yes, that's more or less it. The primary reason that it's so easy is the code generation, which means that

  • Modules are automatically created, just annotate EntryPoint classed with @gwt.module
  • Services are configured and interfaces are generated by annotating RemoteServiceServlet classes with @gwt.interface
  • Remote methods are made available when they are annotated with @gwt.serviceMethod
  • Access to the remote services goes through a ServiceFactory, which handles url mapping automatically.

For more complex applications, it's probably not necessary (or desirable) to generate web.xml, so just use it as a starting point. You'll probably add filters and other stuff later.

Have fun!

4 People had this to say...

Gravatar
  • Bryce Benton
  • September 29th, 2006
  • 3:58 pm

Thank you for the great write up about deploying GWT with ant.

The build.xml file references ant-gwt.xml. Can you please post the contents of this file?

Thanks,
Bryce

Gravatar
  • recht
  • September 29th, 2006
  • 4:03 pm

The file is located in gwt-ant.jar, which you should place in lib/build. If you’ve modified the build file for your own project, you should make sure you’ve got all the jar files in your local lib dir, and the classpath element should include jar/classes in the right order.

Gravatar
  • Bryce Benton
  • September 29th, 2006
  • 4:34 pm

Nevermind. I figured it out.

Follow the instructions from this other GWT write up and place the ant-gwt-*.jar file in the project’s lib folder.

Nice!

Gravatar
  • Bryce Benton
  • September 29th, 2006
  • 5:27 pm

Thanks. Your solution from 4:03pm looks to be more elegant than mine from 4:34pm.

Once again, thanks for the help.

–bryce

Want your say?

* Required fields. Your e-mail address will not be published on this site

You can use the following XHTML tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>