Hanumant’s Java Workshop

Turbo Charged Java Development!

Debugging GWT project using Netbeans and Maven without the damn Plugins

My favourite Java editor is NetBeans and I love Maven. So when sometime ago I was developing a GWT application, I was disappointed to learn that

  1. GWT directory structure was not same as Maven standard directory structure.
  2. Google hasn’t provided any plugin for Netbeans.
  3. Third party NetBeans plugins that claimed to get you started with GWT quick were hopeless.

I tried GWT4NB and GWT Maven Plugin. After playing with these plugins for a couple of days, I just couldn’t get them to work the way I wanted. I wanted –

  1. Latest GWT version (2.1.0.M1),
  2. Netbeans v6.8 IDE,
  3. Maven 2.0 Directory Structure,
  4. and the ability to debug the GWT app in Netbeans (along with break points and all) .

Finally, I gave up on the plugins and decided to set up the whole project myself so that I could satisfy my requirements. The following is a documentation of what needs to be done to do this. This approach allows you to work with new releases as well.

Prerequisites/Assumptions

  1. Basic knowledge of developing a regular JEE Web Application. You should know what file goes where.
  2. Basic knowledge of Maven –
    1. You should be able to create a simple web app project in Maven directory structure.
    2. You should be able to add a jar in your local Maven Repository
    3. Maven ant plugin – This plugin allows you to run any Ant task while building a project. Maven will automatically download it so you don’t have to do anything here. Just be aware.
  3. GWT – You should know the how GWT works. This article is not about how to develop GWT apps. It is about how to debug GWT app in Netbeans.
  4. Netbeans – Netbeans is capable of opening a Maven project without any modifications.

Setting up the infrastructure –

  1. Download and install GWT wherever you like on your machine. You need it to get the various jar files and the gwtc compiler. I have it in c:/gwt-2.1.0.M1
  2. Create your Maven Web App project (empty shell, with a Hello World index.jsp to begin with)  wherever you like. Since a Maven Web App has a standard directory structure, Netbeans has nothing to do with it. We will add GWT related things to appropriate directories in this web app later.
  3. In your Web app’s POM, you will add the following dependencies.         
           <dependency>
                <groupId>com.google.gwt</groupId>
                <artifactId>gwt-servlet</artifactId>
                <version>2.1.0.M1</version>
            </dependency>
            <dependency>
                <groupId>com.google.gwt</groupId>
                <artifactId>gwt-user</artifactId>
                <version>2.1.0.M1</version>
                <scope>provided</scope>
            </dependency>

    So add these two jar files (they are in the GWT installation directory) in your Maven repository. You can do this either by deploying it by mvn command or by directly putting them in appropriate directory in Maven repo. This is standard Maven stuff. Nothing to do with GWT.

Your Java code can be categorized into three kinds –

  1. server side code – e.g. business logic, DAO etc.
  2. the code that will be converted into JavaScript and used only on the client side – e.g. GUI screens.
  3. the code that is used by server side and the client side- e.g. Data transfer objects and Service interfaces . These classes will be used by the server side and these classes will also be converted into Java Script and will be used by the client side code.

In a Web App, the server side code has to be in the WEB-INF/classes and the Java Script files generated from the Java Code must be in the document root of the web app.

As you know, GWT development requires the following two changes in your regular Web App development process –

  1. Before you can build your WAR file , you need to first compile your Java code of kind 2 and 3 to JavaScript. This compilation is done by the GWT compiler, which is implemented by com.google.gwt.dev.Compiler class.
  2. Unlike a regular webapplication, “Debugging” a GWT application actually involves “Running” the  GWT’s custom webserver in Debug mode. This custom webserver is implemented by com.google.gwt.dev.DevMode class and this is exactly what is invoked when you run “ant devmode”.Note: Debugging the GWT WebApp directly like a regular web app will only allow you to the debug the server side code. Indeed, because the IDE has no knowledge of the Java Code that was used to generate the JavaScript code.  Obviously, this is not what you want. You want to be able to debug the client side Java Code.

So basically, if you are able to do the above two changes in your build process, you are home free.  The following is how you can do it:

Add two new profiles in the profiles section of the project’s POM – one that adds a the GWT compile step in the build step and another that runs the DevMode class in the debug step.

Note: Do not let the size of the following profiles scare you. They are very straight forward.

        <profile>

              <!– your objective in this profile is to attach an ant task in the compile phase. –>
            <id>build-with-gwtc</id> <!– This is the name of your profile. Can be anything. –>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <build>
                <plugins>
                    <plugin> <!– configure antrun plugin –>
                        <artifactId>maven-antrun-plugin</artifactId>  
                        <version>1.4</version>
                        <executions>
                            <execution>
                                <id>gwtc</id>
                                <phase>compile</phase> <!– you want to run the task in compile phase –>
                                <configuration>
                                    <tasks> <!– this is the ant task that you want to run. The task is to run the GWT Compiler, which is a java class. –>

                                         <java failonerror=”true” fork=”true” classname=”com.google.gwt.dev.Compiler”>
                                            <classpath> <!– configure the classpath for the GWT compiler. It needs these jars. –>
                                                <pathelement location=”${gwt.sdk}/gwt-user.jar”/> <!– gwt.sdk is a variable defined in properties section below–>
                                                <pathelement location=”${gwt.sdk}/gwt-dev.jar”/>
                                                <pathelement location=”${gwt.sdk}/gwt-servlet.jar”/>

 

                                                <!– This is where all your Java code exists. Remember, GWTC needs raw Java code and not class files. So it needs to know where to find the java code.–>
                                                <pathelement location=”src/main/java”/> 

 

                                                <!– all your resource files such as spring configuration file exist here.  This location is specified here because it also contains MyGWTMain.gwt.xml file. –>
                                                <pathelement location=”src/main/resources”/>


                                            </classpath>
                                            <jvmarg value=”-Xmx256M”/> <!– GWT compiler needs some extra memory –>

  

                                            <!– These arguments are straight from google provided build.xml file –>

 <!– -war target/${webappctxname}  tells GWTC that all the web app code is in target/${webappctxname} directory. This is the same place where Maven puts the web app after building the webapp.  GWTC is the last step of the build process. –>

<arg line=”-gen gen -war target/${webappctxname} -style PRETTY”/>

 

   

                                            <!–  Notice that you don’t specify all the Java files that you want GWTC to compile here. You specify only the entry point. It figures out the rest using MyGWTMain.gwt.xml file. This is a standard GWT configuration file and it should be in src/main/resources/com/mycompany directory –>

                                         <arg value=”com.mycompany.MyGWTMain”/>
                                        </java>
                                    </tasks>
                                </configuration>
                                <goals>

                                    <goal>run</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>

 

        <profile>

 <!– your objective in this profile is to run GWT’s custom web server in debug mode. Most of the stuff is same as above.–>
            <id>debug-gwt</id>


            <activation>
                <activeByDefault>false</activeByDefault>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <artifactId>maven-antrun-plugin</artifactId>
                        <version>1.4</version>
                        <executions>
                            <execution>
                                <id>devmode-debug</id>
                                <phase>compile</phase>
<!– you can probably change it to a different phase. –>

                                <configuration>
                                    <tasks>

                                         <!– you are going to run  com.google.gwt.dev.DevMode class. So below, you are just specifying its classpath and the arguments. –>
                                        <java failonerror=”true” fork=”true” classname=”com.google.gwt.dev.DevMode”>
                                            <classpath>
                                                <pathelement location=”${project.basedir}/target/${webappctxname}/WEB-INF/classes”/>
                                                <pathelement location=”${gwt.sdk}/gwt-user.jar”/>

                                                 <fileset dir=”${gwt.sdk}” includes=”gwt-dev*.jar”/>
                                                <fileset dir=”${project.basedir}/target/${webappctxname}/WEB-INF/lib” includes=”**/*.jar”/>
                                                 <!– the following is rquired because that’s where DevMode will find the java code for the GWT javascripts. –>
                                                <pathelement location=”${project.basedir}/src/main/java”/>
                                                <pathelement location=”${project.basedir}/src/main/resources”/>

                                            </classpath>
                                            <jvmarg value=”-Xmx256M”/>
                                            <jvmarg value=”-Xdebug” />

 

                                           <!– This will cause the process to open a up port 5555  for debugger. –>
                                            <jvmarg value=”-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5555″ />

                                            <jvmarg value=”-Xnoagent”/>
                                            <jvmarg value=”-Djava.compiler=NONE”/>   

                                            <!– The following arguments are for the GWT WebServer DevMode –>
                                           <arg value=”-startupUrl”/>
                                            <arg value=”MyGWTMain.html”/>
                                            <arg value=”-war”/>

                                            <arg value=”target/${webappctxname}”/>

                                             <arg line=”${gwt.args}”/>
                                            <arg value=”com.mycompany.MyGWTMain”/>
                                        </java>
                                    </tasks>
                                </configuration>
                                <goals>
                                    <goal>run</goal>
                                </goals>
                            </execution>
                        </executions>

                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
    <properties>
        <gwt.sdk>c:/gwt-2.1.0.M1</gwt.sdk>
        <gwt.args></gwt.args>
        <webappctxname>webets</webappctxname>

        <!– The following are added by netbeans. –>

        <netbeans.hint.deploy.server>Tomcat60</netbeans.hint.deploy.server>
        <project.build.sourceEncoding>windows-1250</project.build.sourceEncoding>
        <project.basedir>C:/temp/works/webets</project.basedir>
    </properties>

 

How to use the above configuration

  1.  To build the project – In your Netbeans project explorer, Right Click on your project. You should see two new profiles – build-with-gwtc and debug-gwt. Select “build-with-gwtc”. Now, again right-click on the project and select “clean and build”. This will cause it to first compile (using javac) all your java code and put the class files and resource files in appropriate directory in “target” and then it will execute the ant task, which calls the GWTC compiler. It will generate the JavaScript for all the permutations. Finally, it will build the War file.
  2. To debug the project –  In your Netbeans project explorer, Right Click on your project and select the profile debug-gwtc. Now, again right-click and select “Build”. Do not select Run or Debug. Remember, we have modified the build step to execute ant java process in debug mode. Once you click build, it will execute DevMode class in a separate process and you should see a message “Listening for transport dt_socket at address: 5555”. You can now go to Debug menu and select Attach Debugger to attach to this process.

 This may look like a lot of steps but it is actually quite simple and transparent. This approach allowed me to learn how exactly GWT works.

 

September 22, 2010 Posted by | Java | 5 Comments