Monday, November 30, 2009

Incorporating GWT into your project structure

GWT Release: 1.7.1

Problem: I wanted to use GWT in one of my project. I first played around with a fresh project generated using the eclipse plugin for GWT. All went well until I decided to integrate it into another project I already had.
Now this old project was a "Dynamic Web Project" which has a different folder structure than a GWT plugin created project.

GWT comiler puts all output in a "war" directory directly under project dir (MyProject/war)
Since all the JS and other artifacts generated are under this directory, they are not accessible from the browser when the Dynamic Web Project is run on server.

The trick to make it work is to write a customized Ant build file which would put the gwt generated files into WebContent (the base directory of a deployed web app which  holds WEB-INF etc) instead of "war" folder.

Actually you don't even have to write a build file, just modiy one created by webAppCreator

To create a template application run the following command:

webAppCreator -out MyApplication com.mycompany.MyApplication

This would create standard GWT files including build.xml

Now import files into your existing project as follows:
Say your project's name is MyProject
put
MyApplication.gwt.xml > src/com/mycompany/
x/y/z.java > src/x/y/
build.xml > MyProject/
put other files like htmls and css scripts at appropriate places in WebContent

Now add this line in the gwtc and hosted mode tasks to override the default location for GWT compiler:output.
<arg line=" -war WebContent"/>

---------------------------------------------------------------------------------------
  <target name="gwtc" depends="javac"  description="GWT compile to JavaScript">
    <java failonerror="true" fork="true" classname="com.google.gwt.dev.Compiler">
      <classpath>
        <pathelement location="src"/>
        <path refid="project.class.path"/>
      </classpath>
      <!-- add jvmarg -Xss16M or similar if you see a StackOverflowError -->
      <jvmarg value="-Xmx256M"/>
      <jvmarg value="${XstartOnFirstThreadFlag}"/>
      <jvmarg value="${d32Flag}"/>
      <arg line=" -war WebContent"/>
      <!-- Additional arguments like -style PRETTY or -logLevel DEBUG -->
      <arg value="com.mycompany.MyApplication"/>
   </java>
  </target>

and

  <target name="hosted" depends="javac" description="Run hosted mode">
    <java failonerror="true" fork="true" classname="com.google.gwt.dev.HostedMode">
      <classpath>
        <pathelement location="src"/>
        <path refid="project.class.path"/>
      </classpath>
      <jvmarg value="-Xmx256M"/>
      <jvmarg value="${XstartOnFirstThreadFlag}"/>
      <jvmarg value="${d32Flag}"/>
      <arg line=" -war WebContent"/> 
      <arg value="-startupUrl"/>
      <arg value="MyApplication.html"/>
      <!-- Additional arguments like -style PRETTY or -logLevel DEBUG -->
      <arg value="com.mycompany.MyApplication"/>
    </java>
  </target>

Run the build target. It should generate Java > JS files and other GWT artifacts in a new folder under WebContent. In this case it is myapplication

Now run the hosted target in build.xml. The hosted browser should now run without a hitch!!

You may also want the run application on server the way you normally the application on the server (Run As> Run on Sever)

Instead of firing a build every time, you can automate this process by going the project menu and adding the Ant build task in Builders