Create GWT “Hello World” with IDEA Tutorial

Posted by

Introduction

If you are not familiar with GWT basics please read these tutorials: GWT Introduction, Anatomy of a GWT project. To learn more about GWT, I recommend reading these good books – GWT Solutions, GWT Applications, AJAX Security.

In this tutorial, I will walk you through the tasks you need to perform in IDEA 7 to create a working project. We won’t be doing too many interesting things in the code generated in this tutorial, rather, the idea is to get you familiar with the mechanics of creating GWT projects with IDEA.

The GWT plugin is bundled with IDEA 7 by default, if you have an older version of IDEA, you can get the plugin here. If you don’t have IDEA, you can download it here, and get a 30 day eval license.

In this tutorial we will cover the following topics:

  1. creating a new GWT project in IDEA
  2. using IDEA to manipulate the project structure and add resources (like stylesheets and images)
  3. using IDEA to create a web facet, for deployment to an app server/servlet container (if you don’t want to use just hosting mode)
  4. add some code to a sample project to display a loading image, and then remove the image, once the GWT app has loaded (this will be made part of a GWT Utility class that you can download, along with the other project files/resources at the end of the tutorial).

Step 1. Create a new GWT project

Launch IDEA, and create a new project from scratch. Call this project “sample”. Make sure to check the “Google Web Toolkit” checkbox in the “Please select desired technologies” screen. Here are screenshots of all the steps:

  1. image
  2. image
  3. image

Step 2. Create a sample application (that we will heavily modify)

Locate the “src” folder in your project view, and right click on it, to create a new project as shown here:

Give this sample application a name like “SampleApp”:

image

IDEA will generate a sample app for you that has a simple UI that’s tied to an RPC service. It will also generate a sample project structure and an HTML host page that we are going to modify. This is what you should have in your project now:

Here are some notes on the project structure:

  1. IDEA create a root folder called “sampleApp”. There is a SampleApp.gwt.xml (module file) that’s in this folder, which holds all kinds of information about your app).
  2. The client folder is where all the Java classes for the client app that runs in the browser go.
  3. The public folder is where all kinds of resources can be stored. These can be images or stylesheets. Any resources you put in this folder can be referenced from you code or the XML module configuration file as if it was in the “root” folder.
    • For example, let’s say you have an image named “image.jpg” in this folder, and you want to reference it in your client code. You would just write something like this: Image img = new Image(“image.jpg”);. There’s no need to prepend any path info (project name or “sampleApp” folder name) to this filename.
    • Similarly, if you want to reference something in the public folder from your XML module configuration, there’s no need to figure out where the file is, just reference it by name.
    • Now, if you have folders that are inside this public folder, then you will have to provide that subfolder name. For eg, if you have “image.jpg” in “backgrounds” folder, then you would write something like: Image img = new Image(“backgrounds/image.jpg”);.
    • Think of it this way, the “public” folder is in the classpath, and you don’t have to figure out where it actually is. However, if you have subfolders inside the public folder, then you have to provide the name the subfolders.
  4. The server folder is where any RPC service implementations go.
  5. XML module configuration file – this file name usually contains the name of your module itself, and information about what the entry point class is in your project. You can also add stylesheet information here as well, so that this doesn’t have to be specified in the HTML Host page.

Let’s modify this project:

Change the name of the HTML host page from SampleApp.html to index.html. Click on SampleApp.html in your project view, then press Shift + F6, to change the name of it:

Open up index.html and make these changes:

  1. Remove the <style> tag and it’s contained elements. We will put all the styles in a separate style sheet that we will create.
  2. Remove the <meta name=”gwt.module” … > tag. We are going to simplify this HTML file and make it so that you don’t have to touch any meta tags in the head element.
  3. Remove the tag from the file as well. We are going to simplify this as well.
  4. Add the following script tag:
    sampleApp.SampleApp.nocache.js”>
    sampleApp” is the name of the folder under src, and “SampleApp” is the name of the XML module file. The file ending in .nocache.js is what is generated by GWT when you deploy your app. If you change the folder name from “sampleApp” to something else, then this file name will have to be updated.
  5. Remove the “<p>” tag an it’s enclosing content.
  6. Add the following line, referencing the loading image:

    loading.gif”>Loading app…

    This loads the “loading.gif” image when the HTML file is loaded, and we will remove this programmatically once the app starts up in sections below. We will add this gif file to the public folder soon.

The following is a listing of this index.html file (without any style sheet references, and meta tags):

<html>
<head>
  <!--                                           -->
  <!-- Any title is fine                         -->
  <!--                                           -->
  <title>Wrapper HTML for App</title>
</head>
<!--                                           -->
<!-- The body can have arbitrary html, or      -->
<!-- you can leave the body empty if you want  -->
<!-- to create a completely dynamic ui         -->
<!--                                           -->
<body>
<!--                                            -->
<!-- This script is required bootstrap stuff.   -->
<!-- You can put it in the HEAD, but startup    -->
<!-- is slightly faster if you include it here. -->
<!--                                            -->
<script language="javascript" src="sampleApp.SampleApp.nocache.js"></script>
<!-- OPTIONAL: include this if you want history support -->
<iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"></iframe>
<h1>Sample Application</h1>
<div id="loading"><img src="loading.gif">Loading app...</div>
<table align=center>
  <tr>
    <td id="slot1"></td>
    <td id="slot2"></td>
  </tr>
</table>
</body>
</html>

The reason for doing all of this is to show you how everything is “bound” to each other, and how to load resources. Also, if you have to embed your GWT app in existing web apps, portals, or blogs, then not having to insert meta elements in the head tag makes life simpler. And sometimes you might not even have access to the head tag in case you are using a hosted blog or something.

Adding stuff to the public folder:

We are going to add a “loading.gif” image to the public folder as well as adding a style sheet called “Style.css”. Simply copy these files into the “src/sampleApp/public/” folder outside of IDEA.

You can download “loading.gif” here :

Here’s a listing of “Style.css”:

h1 {
  font-family: Tahoma, sans-serif;
}
body {
  background-color: white;
  color: black;
  font-family: Lucida Grande, Segoe UI, sans-serif;
  font-size: small;
  margin: 8px;
}

Modify SampleApp.gwt.xml:

We are going to modify the XML module descriptor file now and add a reference to the “Style.css” file in there. The reason to do this is to simplify the HTML host page, so that we can embed GWT apps more easily in some environments. Just add the following line to the XML file:

<stylesheet src=”Style.css”/>

Here’s a listing of the XML file:

<module>
  <!-- Inherit the core Web Toolkit stuff.                  -->
  <inherits name='com.google.gwt.user.User'/>
  <!-- Specify the app entry point class.                   -->
  <entry-point class='sampleApp.client.SampleApp'/>
  <!-- Specify the app servlets.                   -->
  <servlet path='/sampleApp.SampleApp/SampleAppService' class='sampleApp.server.SampleAppServiceImpl'/>
  <stylesheet src="Style.css"/>
</module>

Step 3. Create a Run/Debug configuration for your app

Now that you’ve made all these changes, let’s test them to make sure everything runs as expected. For this you have to create Run/Configuration settings for this GWT Project. Add a new “GWT Configuration” from your “Run/Debug Configuration” dialog box, and then change the name of it from “unnamed” to “Sample App”, and select which HTML host page to load. Use the screenshots below to guide you:

Save these settings and run the app:

image

As you can see, the message on the top of this browser page has a different font applied to it, as defined in our style sheet, and there’s a loading image displayed as well. If you click on “Click me”, you will see the messages on the browser have also been formatted according to our style sheet. The style sheet defined styles for the <h2> and <body> elements.

Step 4. Create an application loading splash screen for your app

Notice that when you run your app, the “Loading app…” image stays on the browser window even after your GWT app has loaded. We will fix this now. Locate the “SampleApp.java” in your project window and add the following lines to the “onModuleLoad” method:

// remove the loading message from the browser
com.google.gwt.user.client.Element loading = DOM.getElementById("loading");
DOM.removeChild(RootPanel.getBodyElement(), loading);

Earlier in this tutorial, we created a <div> element called “loading” in the HTML host page. When the GWT app loads, we can actually remove this page from the browser, by manipulating it’s DOM.

This is what your SampleApp.java file should look like:

package sampleApp.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.DOM;
/** Entry point classes define <code>onModuleLoad()</code>. */
public class SampleApp implements EntryPoint {
/** This is the entry point method. */
public void onModuleLoad() {
  final Button button = new Button("Click me");
  final Label label = new Label();
  button.addClickListener(new ClickListener() {
    public void onClick(Widget sender) {
      if (label.getText().equals("")) {
        SampleAppService.App.getInstance().getMessage("Hello, World!", new MyAsyncCallback(label));
      }
      else {
        label.setText("");
      }
    }
  });
  // Assume that the host HTML has elements defined whose
  // IDs are "slot1", "slot2".  In a real app, you probably would not want
  // to hard-code IDs.  Instead, you could, for example, search for all
  // elements with a particular CSS class and replace them with widgets.
  //
  RootPanel.get("slot1").add(button);
  RootPanel.get("slot2").add(label);
  // remove the loading message from the browser
  com.google.gwt.user.client.Element loading = DOM.getElementById("loading");
  DOM.removeChild(RootPanel.getBodyElement(), loading);
}
static class MyAsyncCallback implements AsyncCallback {
  public void onSuccess(Object object) {
    DOM.setInnerHTML(label.getElement(), (String) object);
  }
  public void onFailure(Throwable throwable) {
    label.setText("Failed to receive answer from server!");
  }
  Label label;
  public MyAsyncCallback(Label label) {
    this.label = label;
  }
}
}

Run the app again, and you should see the “Loading app…” message go away once your app is started. Here’s a screenshot:

Step 5. Add a web facet, for deployment to an app server/servlet container (like Tomcat)

The final step in this tutorial is to prep your project for deployment to an app server. You will have to add a web facet to your Project Configuration, and you will have to add an extra JAR file called “gwt-server.jar”. The gwt-user.jar file which IDEA adds automatically to your project contains servlet classes which are going to cause problems when deployed on an app server (since the app server has it’s own servlet API classes). Finally, you have to bind the GWT app configuration to this facet. Here are the steps:

1. Launch your project settings (Ctrl + Alt + S)

2. Add a Library

3. Name it “gwt-server”

4. Select the “sample” module to add a dependency to

5.Now attach classes to this project library. Locate your GWT 1.4.x install and find the “gwt-server.jar” file

6. Now select the Modules settings

7. Add a new Web Facet

image

8. Change the packaging method for the gwt-server library

9. Add your app server specific descriptor next. I’m using Tomcat, so I will show you how to set it up for Tomcat… IDEA supports lots of app server configurations, so select what works best for your physical deployment environment

10. Click on Java EE Build Settings and specify how you want your web app to be deployed. I’m going to have it generate a WAR file.

11. One final step, make sure to associate the GWT facet with the Web facet as shown here:

Note: If you find your web.xml file is empty (just has a namespace) then follow these steps:

  1. Open the SampleAppServiceImpl class in your project view
  2. Place your editor cursor on the class name and wait for the Inspection to pop up like this:
  3. Let IDEA register the remote service for you, and your web.xml will be empty no more!

Running the web app in Tomcat

You can now take your WAR file, (or exploded directory) and upload it to your app server/servlet container. The WAR file in this example is called “Web.war” and it’s located in the “./sample/out” folder. The “sample” folder is the root folder for this project (the “src” folder is inside of it as well). We choose the name “Web.war” when we named our Web facet “Web”.

Once deployed into the Tomcat container, by copying the “Web.war” file to the “$TOMCAT_HOME$/webapps” folder, and assuming that your Tomcat instance is running on localhost, port 8080, the URI that you have to type into your browser to access this app is:

  • Tomcat URI: http://localhost:8080/Web/sampleApp.SampleApp/index.html

Please note that there is a “/Web” path inserted into the URI. This is because the WAR file is deployed to the “Web” folder, since that’s the name of the WAR file itself, as we configured in the Web facet settings. So the three things to keep in mind are:

  1. host name of tomcat – in this case “localhost”
  2. port number of tomcat – in this case “8080”
  3. name of WAR file – in this case “Web”.

Given these 3 pieces of information, you can come up with the URI that you will need to access your web app hosted in Tomcat.

Contrast this to the URI for the hosted mode environment:

Note, that there is no “/Web” in this hosted mode URI. And the port is “8888”.

Also note that you can use IDEA itself to deploy this Web facet into Tomcat. That procedure is not covered in this tutorial. What I’ve shown you here will make it easy to deploy the WAR file to a remote host that’s running your Tomcat instance, for example.

Why does the <servlet-url> mapping in web.xml look funny?

Those IntelliJ guys are pretty smart 🙂 . The reason their strange URL in the web.xml file works is due to the following reason:

1. What does GWT.getModuleBaseURL() resolve to?

When running in hosted mode, this is the GWT.getModuleBaseURL():

When running in Tomcat, using the URI that you used from the section above, this is the GWT.getModuleBaseURL():

2. What is the complete URI that the GWT code composes to make the RPC call to the servlet?

So, for the GWT app to get a stub for the service, it uses the following code (from SampleAppService.java):

setServiceEntryPoint(
  GWT.getModuleBaseURL() +
  "sampleApp.SampleApp/SampleAppService");

3. What is the URI as far as Tomcat is concerned?

Here’s the URL pattern in web.xml:

  • <url-pattern>/sampleApp.SampleApp/sampleApp.SampleApp/SampleAppService</url-pattern>

Which means that the actual URI is (don’t forget the web app is deployed to $TOMCAT_HOME$/Web/ folder):

4. Comparing the GWT client side URI to the Tomcat URI… they must be the same!

Now, on the GWT app side, if we add up the GWT.getModuleBaseURL() + “sample.App.SampleApp/SampleAppService” (from our Java code):

  • “http://localhost:8080/Web/sampleApp.SampleApp/” + “sampleApp.SampleApp/SampleAppService”

Both the GWT URI and the Tomcat URI are the same! So, in the end all these paths add up correctly. Whew! 🙂

How do I make the <servlet-url> mapping simpler?

By default, the GWT plugin deploys any RPC servlets with a default app context (which is the name of your GWT module). You can simplify this, if you know you are not going to deploy your web app to the ROOT context of a tomcat container, by taking the following steps:

1. Load the project settings and goto the GWT facet, and select the Output Relative Path field:

image

2. Remove the Output Relative Path:

image

Note: if don’t want to leave this output relative path blank, but want to use your own, then don’t forget to prepend a “/” in front of your string… otherwise you will get servlet deployment errors in Tomcat! So if you want to remove it, just leave it bank, but if you want to change it, then prepend the “/” to your new path.

3. Open the web.xml file in IDEA, and let it fix your servlet mapping for you:

image

This will remove the extra “sampleApp.SampleApp” from the url-pattern:

  • <url-pattern>/sampleApp.SampleApp/SampleAppService</url-pattern>