In this article, you'll use Apache Tomcat as your example servlet container, because it's both widely used and available at no cost. Other servlet containers will behave similarly. You'll often be deploying to an existing server; but if not, the links in the Resources section at the end of this article point you to the Tomcat download location. If you're running the Microsoft® Windows® operating system, Tomcat has a binary installer for Windows that's relatively simple to use. If you're on a Mac or a UNIX® system, there's a compiled version that you can extract and place in a convenient location (/usr/local is common); after setting a few environment variables, you're good to go.
Broadly speaking, there are two steps to deploying your GWT application in Tomcat.
- Gather all the files you'll need and put them where Tomcat can see them.
- Make Tomcat aware of all the server-side actions you call from your GWT page.
The process has a few more steps than is desirable, and as of this writing there's no official method of automating it. I describe the manual process here. By the time you read this, however, there may be more robust tool support for deployment.
- Locate your Tomcat installation's root directory. One level down from that directory you'll see a subdirectory called webapps. Every application running within the Tomcat servlet container gets its own directory there. So create a directory called slicr within webapps. The structure of a Java server-side application is set by the servlet standard, and all servlet runners should support the same structure.
- Within your slicr directory, create a subdirectory called WEB-INF -- and yes, the capitalization is important.
- To your slicr directory, move both your GWT-compiled JavaScript pages and your normally compiled Java classes. I'll show how to do the Java classes first.
- Compile your Java code as you normally would, using your integrated development environment (IDE), Apache Ant, or whatever you wish. You have a couple of options at this point:
- The quickest option is to copy your entire tree of .class files to the Tomcat subdirectory webapps/slicr/WEB-INF/classes, which Tomcat automatically places in the classpath variable of your webapps directory when run.
- Alternately, you could convert the compiled classes to a JAR file using the tool of your choice, and then place that JAR file in the webapps/slicer/WEB-INF/lib directory. Again, Tomcat places the JAR file in that directory in your classpath variable.
Next up, compile and move your GWT client files. Because you've done most of your work in hosted mode, you've been able to skip performing this step explicitly to date. The quickest way to compile your code is to use the Compile button from the hosted mode console. But there's another way that might be more convenient for automating.
In Part 1 of
this series, you used the GWT applicationCreator script to create your GWT
project. At the time, I casually alluded to "a couple of shell scripts" created
along with the GWT project files but didn't go into more detail.
One of the shell files created is called Slicr-compile. In Windows, the file also has a .cmd extension. (Generically, of course, it's your project name-compile.) Invoke the file from a command line, or click it depending on your operating system. The script putters around for a while before outputting something like this:
Output will be written into ./www/com.ibm.examples.Slicr
Compilation succeeded
What's happening here is that GWT is compiling all your client-side Java code
into JavaScript code. Client-side code, by default, is all the code in your
project's client source directory; however, you can explicitly change
that directory in your project .gwt.xml file by adding a tag of the form
<source path=path/>, where path
is the source path you want to add. Note that the default path is no longer
included if you add your own path, so if you also want the default path, you
must add it explicitly.
The GWT compiler usually converts legal Java code successfully. However, some items will cause problems. Following are some things to be particularly aware of:
- GWT client code must be compatible with Java 1.4. That means no generics, no autoboxing, and no new-style for-each loop. Supposedly, Java 1.5 compatibility is planned for the future.
- Only a minimal subset of the Java Standard Library is supported. Supported library classes are limited to the java.util and java.lang packages. Not all of these packages are supported. In particular, the java.lang.reflect package is not supported. As you saw in Part 2 of this series, this restriction means that you must put items like database code in other parts of your system.
- If you use regular expressions, they are interpreted at run time using the JavaScript rules, not the Java rules.
- Java serialization is not supported. The GWT remote procedure mechanism is used instead, as discussed in Part 3 of this series.
- There are differences in the definition of floating-point numbers and long variable types. Calculations that require strict floating-point semantics should be handled on the server side.
- The GWT compiler ignores Java
assertstatements. Also ignored aresynchronizeddeclarations, as the JavaScript interpreter does not support threading.
Investigate the compilation output
Assuming that your Java code passes those requirements and your compilation is successful, you can follow the output of the compile script and investigate the ./www/com.ibm.examples.Slicr directory, as shown in Listing 1. Some of your file names may differ.
Listing 1. Output from GWT compilation
1A0A627040909C0818A7A71B13246DCD.cache.html 1A0A627040909C0818A7A71B13246DCD.cache.xml 587B8CC6CF487EBD41844000481528BF.cache.html 587B8CC6CF487EBD41844000481528BF.cache.xml 64AF143E1C4C5866446137A8C42B4609.cache.html 64AF143E1C4C5866446137A8C42B4609.cache.xml B01955141995DDAD97AFC2941024CE4E.cache.html B01955141995DDAD97AFC2941024CE4E.cache.xml Slicr.html com.ibm.examples.Slicr.nocache.html gwt.js history.html tree_closed.gif tree_open.gif tree_white.gif |
Easy things first: Slicr.html is the HTML page you coded, copied here directly from your public directory. Anything in the public directory will be placed here. The three .gif files are, as you might expect from their names, used by GWT in rendering tree widgets. Because you have no tree widgets in the Slicr application, you can assume that GWT always puts these images in your output. Moving on to the rest of the files with pronounceable names, history.html has some JavaScript code for managing state and preserving Back button behavior. The gwt.js and nocache.html files both contain more or less boilerplate code designed to start and load your GWT application properly.
Which brings you to the files with the hex digit gobbledygook names. There are six HTML/XML pairs. Open the .html files and you'll see a lot of highly obfuscated JavaScript code, as shown in Listing 2, chosen at random.
Listing 2. JavaScript code
function ob(pb,qb){z();pb.F = qb;return pb;}
function rb(sb,tb,ub){z();sb.D = ub;sb.F = tb;return sb;}
function vb(){}
_ = vb.prototype = new f();_.jb = C;_.hb = E;_.i = 'java.lang.Throwable';
_.j = 1;_.D = null;_.F = null;function wb(xb){mb(xb);return xb;}
function yb(zb,Ab){ob(zb,Ab);return zb;}
function Bb(Cb,Db,Eb){rb(Cb,Db,Eb);return Cb;}
|
Hope that's clear. That's actually your nice, neat Java code compiled to JavaScript code by the GWT compiler. There are five HTML/XML pairs, one for each of the major Web browser rendering engines: Firefox/Gecko (old and new versions), Windows Internet Explorer, Opera, and Safari. The XML files manage some data type mapping so that the correct data types for that engine are used. The obfuscation is there to compress the size of the text file that has to be sent to the browser. When a user hits the GWT page from a browser, the JavaScript code in the boilerplate pages automatically retrieves and loads the correct version of your code for the user's browser.
To deploy your GWT pages, all these files from the www/com.ibm.examples.Slicr directory must be copied into the Tomcat Home/webapps/slicr directory. That takes care of the client side, now onto the server side.
If you've done servlet development before, then this part of the GWT process should be familiar. The server-side code you've written is just another servlet application and is deployed using the Servlet standard.
First, you must compile all your Java code using a plain, ordinary Java compiler. At this point, you have two options:
- You can place all the .class files in the Tomcat Home/webapps/WEB-INF/classes directory.
- Alternately, you can combine all your .class files into a .jar file and place that file in the Tomcat Home/webapps/WEB-INF/lib directory.
The compiled code should include the client-side code you've already compiled using GWT -- remember, you use some of those client classes on the server side to facilitate data transfer.
You must also put any third-party libraries you use in the same /lib directory. This directory always includes the file gwt-servlet.jar, which is itself included with the GWT distribution. This file contains all the GWT user files that your application needs.
Note: The original distribution of GWT did not include this file. However, you still may see Web deployment instructions that involve hacking the gwt-user.jar file to remove servlet classes that would interfere with Tomcat. If your GWT distribution is up-to-date, this step is not necessary.
In this case, you also need the derby.jar file, which is part of the Derby
distribution and which contains the Derby database classes you need. If you want to
transfer the Derby database so as not to lose the toppings data you put into
it, simply place the slicr directory database that Derby created in
Part 2 of this
series. (If you followed the directions in Part 2, this directory should be under
your project top level at the same level with the /src directory.) It doesn't
matter where you put the directory, but the line in the
ToppingServiceImpl class that defines the JDBC URL for Derby must reflect that location:
public static final String PROTOCOL =
"jdbc:derby:[LOCATION OF SLICR DB DIRECTORY]/slicr;";
I placed my Derby database inside the Tomcat webapps/slicr directory, at the same level as the WEB-INF directory, so my code looks like this:
public static final String PROTOCOL =
"jdbc:derby:/usr/local/apache-tomcat-5.5.20/webapps/slicr/slicr;";
Define your server-side calls in web.xml
After your code is visible to the Tomcat servlet container, you must also specifically define all the server-side calls from your GWT application in terms that the Tomcat Web server can understand. Doing so involves defining these server-side calls as servlets in the Tomcat application's web.xml file. Essentially, for each servlet defined in your gwt.xml file like this:
<servlet path="/toppings" class="com.ibm.examples.server.ToppingServiceImpl"/>
you must create a <servlet> and a
<servlet-mapping> tag in the web.xml file.
Listing 3 shows the entire web.xml file for your GWT
project, containing both of these tags for your one
ToppngService servlet.
Listing 3. Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>ToppingService</servlet-name>
<servlet-class>
com.ibm.examples.server.ToppingServiceImpl
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ToppingService</servlet-name>
<url-pattern>/toppings</url-pattern>
</servlet-mapping>
</web-app>
|
Within the web.xml file, the two pieces of information given in your gwt.xml
file are split into two different tags, as part of the Java make-everything-as-verbose-as-possible initiative. The <servlet>
tag takes the fully qualified class name for the servlet, and the
<servlet-mapping> tag takes the URL path name
as you defined it in the GWT file. The two are unified through the common
servlet-name attribute, which can be anything you
like as long as you're consistent. However, it's probably best to use a simple
naming convention, such as the GWT name of the actual service.
Creation of this file is, of course, eminently automatable by any number of
methods ranging from pure text manipulation to XML Document Object Model (DOM)
manipulation. When you've written this file, place it inside your Tomcat
WEB-INF directory. At this point, the Slicr deployment is complete, and you can
test the application by starting Tomcat and typing in the URL, which will be
something like http://localhost:8080/slicr/Slicr.html. If successful, you'll see
the Slicr page just as it was at the end of
Part 3 of this
series.
Troubleshooting deployment problems
| Problem | Cause |
|---|---|
| You don't see anything at all when you type in the URL. | Most likely the cause
is that the Slicr.html page is not in the right place. If you just get Welcome
to Slicr but none of the GWT widgets, you most likely didn't properly place
the GWT JavaScript files. |
| You see the left side of the page but nothing on the toppings pane except the headers. | This means that the server call failed. You'll
have to go to the Tomcat logs to diagnose this problem properly (or
alternately, change the OnFailure() method in the
callback to print an error message to the pane). The first possibility is that
you don't have your Slicr Java class files in place, which is preventing the
servlet from even loading. (This might also happen if the web.xml file isn't
set up properly.) |
| You encounter a Derby failure. | Make sure that the JDBC URL matches the location of the Derby data directory. |
Now that I've described this entire process, you can see that although there are many steps, none of them is particularly complex. I strongly recommend automating your deployment as much as possible by using scripts, Ant tasks, or any other means that work for your project. You'll see one example in Resources, and the various Java IDEs are increasingly adding GWT support, including deployment. Having a one-button deployment saves you a lot of headaches.
Over the course of this article series on GWT, you've built a simple Web application that demonstrates how you can use GWT with a database back end to create a robust Web application with rich client behavior. Even after four articles, you've only scratched the surface of what GWT has to offer. Powerful features -- such as JUnit test integration, using other Web services through JavaScript Serialized Object Notation (JSON) data exchange, and the new GWT internationalization features -- are well worth your time to check out. GWT development continues to grow, and new features and add-on tools are being added all the time. I hope that you'll be able to take a look around and find the tools you need to build the application you want.
Learn
-
Visit the Google Groups
forum for GWT.
-
Check out the official GWT blog.
- Visit the
Apache Derby site for Derby resources.
- Check out the developerWorks Apache Derby project area for articles, tutorials, and other resources to help you get started with Derby today.
- Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products.
- Browse all the Apache articles and free Apache tutorials available in the developerWorks Open source zone.
- Browse for books on these and other technical topics at the Safari bookstore.
- Stay current with developerWorks technical events and webcasts.
- Get an RSS feed for this series. (Find out more about RSS.)
Get products and technologies
-
Download the Google Web Toolkit.
- Innovate your next open source development project with IBM trial software, available for download or on DVD.
-
Download Tomcat.
-
"Google Web Toolkit" (July 2006) by Bruce Perry
contains a sample Ant file to automate many of the tasks described in this
article.
Discuss
- Get involved in the developerWorks community by participating in developerWorks blogs.
Noel Rappin, a Ph.D. from the Graphics, Visualization, and Usability Center at the Georgia Institute of Technology, is a senior software engineer at Motorola. He is also the coauthor of wxPython in Action and Jython Essentials. You can check out Noel's blog at 10printhello.blogspot.com.
Comments (Undergoing maintenance)





