Earlier tonight, we wrapped up a very exciting Campfire One at which we announced that GWT 2.0 is now officially available. In addition to major improvements in the GWT SDK and the Google Plugin for Eclipse, GWT 2.0 includes a brand new performance analysis tool for Chrome called Speed Tracer.
We hinted at it a few weeks ago, and now it's available: Speed Tracer is a powerful new performance analysis tool for Chrome that gives you unprecedented insight into the inner workings of any web application — not just those created with GWT. Want to know why your web app feels sluggish? Speed Tracer can help you find the answer.
It's fun to see Speed Tracer in action, so here's a quick introductory video...
As an aside, Speed Tracer has a pretty snazzy user interface, eh? It was built with GWT.
Here's another quick overview video that highlights some of the cool new features in GWT 2.0...
Now let's talk in more detail about what's new in the GWT SDK and the Google Plugin for Eclipse...
-draftCompile
.ui.xml
.java
GWT.runAsync()
<script>
GWT 2.0 is the culmination of many months of collaborative development, and on behalf of the the entire GWT team, we'd like to thank the WebKit team, with whom we've worked closely to add the low-level instrumentation necessary to make Speed Tracer possible.
And, as always, a huge thanks goes out to the GWT developer community, many of whom have bravely followed the tip of the GWT trunk in svn, trying out new in-progress features and helping find bugs — and even submitting patches to fix them.
Believe it or not, we've still only scratched the surface of what's new. As always, GWT is open source and free to use. We hope you'll give GWT 2.0 a spin.
Download Google Web Toolkit 2.0
Happy coding! See you online.
I've sometimes thought that optimizing web applications is as much a science as dowsing. (No offense intended, dowsers of the world — but you have to admit it's a hard thing to explain even when it does work out.) Even when you are completely willing to invest time and energy into optimizing an application, how do you actually go about it?
Our team, along with everyone else in the world who cares about web application performance, has had to essentially guess at where time goes inside the browser. We've spent countless hours debating each others' wild-eyed speculations as to the true sources of latency afflicting a wide variety of applications. Indeed, web apps can be slow for all sorts of opaque and unintuitive reasons. Don't be fooled into thinking that bloated, slow JavaScript is the only culprit. We've seen pathological situations in which a few seemingly insignificant CSS tweaks can improve performance by a factor of 5 or more. Another dark gem: rearranging a mere few lines of JavaScript that were inadvertently calling DOM-related methods in an unfortunate sequence (which caused multiple redundant layouts) turned a life-negating 5 second operation into a sprightly 50 millisecond blink of an eye. That one took 5 days to find the offending 4 lines of JavaScript and then about 3 seconds to actually make the code change. #nowiamwaybehindingooglereader
We couldn't take it anymore. We decided we had to find a way to transform the witchcraft of optimizing web apps into a legitimate engineering task, once and for all.
My team began working on a series of changes to WebKit and Chrome to collect precise metrics on where time is, in fact, going within the browser. When, exactly, does layout occur? How long does each layout take? Can layout happen synchronously while my JavaScript is executing, or is it deferred? How much time is spent on CSS selector matching? How long does parsing (versus executing) JavaScript take? Does the process of actually painting pixels on the screen take much time? We instrumented the browser way deep down inside to produce a stream of such metrics, being very careful to keep observer effects to a minimum.
Happily, we've managed to land these changes into both WebKit and Chrome over the last several weeks. Soon you'll see the first examples of tools that make these metrics available to web developers using WebKit-based browsers. Of course, we have a lot more instrumentation planned, but the ball is really rolling now thanks to lots of help from the friendly folks on the WebKit and Chrome teams (especially Pavel Feldman and Timothy Hatcher). We've gained many new insights, some of which I mentioned in my Measure in Milliseconds talk at Google I/O earlier this year. When you see these metrics yourself for your own web apps, you'll likely be surprised — and you'll almost certainly wonder how anyone tried to write high-performance code without this sort of insight. Be sure to keep an eye on the Chrome Dev Channel and the WebKit nightly builds for new Inspector features based on our work.
GWT on the go with gwt-mobile-webkit: A new project is underway started by a developer in the GWT community that provides GWT API bindings to HTML 5 features supported by Mobile WebKit. While the project more closely follows the WebKit implementation for HTML 5 features and other WebKit libraries, other browsers are also supported for various HTML 5 APIs. Check out the project homepage for more details.
GWT Gadgets riding the Wave: The Google Wave Gadget API is an awesome way to leverage the power of Wave in your gadgets. Thanks to the efforts of yet another great GWT community member, you can now more easily use the Google Wave Gadget API in your GWT developed Gadgets using the cobogwave project. This library builds on the existing GWT Gadgets support available in the Google API Libraries for GWT project.
GWT-GData v 1.10.1 released: Developed through the guidance of the GWT team, GWT community contributors and the main project lead, Bobby Soares, the gwt-gdata project recently had its 1.10.1 release. This is a nice library to access many of the GData APIs from Google Analytics to Google Maps Data. The full list of supported GData APIs can be found on the project page.
GWT-MVC 0.3 released: The MVC pattern has proven its usefulness in the domain of web application development time and time again. If this pattern is a good fit for the project you're planning or currently working on, you may want to check out the gwt-mvc project, which provides a layer of abstraction to make MVC modeled development easier in GWT.
GWT-Connectors 1.7 released: The gwt-connectors project is a really cool tool for developers who need to connect boxed components with connectors, and now includes connectors with arrow tips. You can check out the demo here, and if you like what you see and need it for your application, check out the project page for more information.
If you don't use Mac OS X 10.6 (Snow Leopard), the GWT 1.7.1 release shouldn't interest you much -- you shouldn't see any changes. If you do use Mac OS X 10.6, good news. Running GWT with Java 6 has become simpler. Download it here.
GWT's hosted mode uses the Standard Widget Toolkit (SWT), which only supports 32-bit operation. Hosted mode must therefore also run a 32-bit version of Java. Mac OS X 10.5 (Leopard) shipped with a 32-bit Java 5 and a 64-bit only Java 6. Java 5 was compatible with the 32-bit SWT bindings, so the GWT SDK directed users to use Java 5 only. With the Snow Leopard release, Apple only includes Java 6, but it now runs in both 32-bit and 64-bit modes.
In short, you can now run GWT on Snow Leopard using the Java command line argument -d32 without further modification. The GWT SDK no longer directs you to only use Java 5, and the ant scripts (including scripts generated by the webAppCreator tool) have been updated to include the -d32 flag where necessary. Also, Linux users will see a more informative error message when a non-32-bit Java runtime is used..
class RaphaelJS extends JavaScriptObject { protected static class Shape extends JavaScriptObject { public final native Shape rotate(double degree, boolean abs) /*-{ return this.rotate(degree, abs); }-*/; public final native Shape scale(double sx, double sy) /*-{ return this.scale(sx, sy); }-*/; public final native Shape translate(double dx, double dy) /*-{ return this.translate(dx, dy); }-*/; // ... } /** * factory method */ static public final native RaphaelJS create(Element e, int w, int h) /*-{ return $wnd.Raphael(e, w, h); }-*/; public final native Element node() /*-{ return this.node; }-*/; public final native Shape circle(double x, double y, double r) /*-{ return this.circle(x,y,r); }-*/; public final native Shape rect(double x, double y, double w, double h) /*-{ return this.rect(x, y, w, h); }-*/; // ... }
public class Raphael extends Widget { private RaphaelJS overlay; public class Shape extends Widget { protected RaphaelJS.Shape rs; protected Shape(RaphaelJS.Shape s) { setElement(s.node()); rs = s; } public Shape rotate(double degree, boolean isAbsolute) { rs.rotate(degree, isAbsolute); return this; } public Shape scale(double sx, double sy) { rs.scale(sx, sy); return this; } public Shape translate(double dx, double dy) { rs.translate(dx, dy); return this; } // ... } public class Circle extends Shape { public Circle(double x, double y, double r) { super(overlay.circle(x, y, r)); } } public class Rectangle extends Shape { public Rectangle(double x, double y, double w, double h) { super(overlay.rect(x, y, w, h)); } public Rectangle(double x, double y, double w, double h, double r) { super(overlay.rect(x, y, w, h, r)); } } public class Text extends Shape { public Text(double x, double y, String str) { super(overlay.text(x, y, str)); } } // ... public Raphael(int width, int height) { Element raphaelDiv = DOM.createDiv(); setElement(raphaelDiv); overlay = RaphaelJS.create(raphaelDiv, width, height); } }
public class MyDrawing extends Raphael { public MyDrawing(int width, int height) { super(width, height); Circle c = new Circle(width/2, height/2, 20); // Raphael automatically appends the Circle to this drawing } } public class MyApp implements EntryPoint { public void onModuleLoad() { MyDrawing d = new MyDrawing(Window.getClientWidth(), Window.getClientHeight()); RootPanel.get().add(d); } }
public class SelectRoleHandler implements DatabaseRequest.Handler { public void handle(DatabaseRequest.Result result) { for (int row=0; row < result.getRowCount(); row++) { JSONObject data_row = result.getRowValues(row); Role r = new Role(data_row); // process role... } } }
public class SelectRoleCallback implements RequestCallback { public void onError(Request request, Throwable exception) { Window.alert("Couldn't retrieve JSON"); } public void onResponseReceived(Request request, Response response) { if (200 == response.getStatusCode()) { JSONArray data_set = JSONParser.parse(response.getText()).isArray(); if (data_set != null) { for (int row=0; row < data_set.size(); row++) { JSONObject data_row = data_set.get(row).isObject(); Role r = new Role(data_row); // process role... } } } else { Window.alert("Couldn't retrieve JSON (" + response.getStatusText() + ")"); } } }
Recently I was shown a demo of Seesmic Web, an application that lets you manage multiple streams and Twitter accounts. The demo was very cool and notable because Seesmic's related product is Seesmic Desktop, implemented in Adobe Air. Seesmic Web replicates the desktop functionality, but on the web using GWT.
The team chose GWT to build Seesmic Web, and I was curious to hear about their experience. In case it helps others in the process of evaluating GWT for building web apps, here is the response I got back from Johann Romefort, CTO at Seesmic.
The choice of using GWT was nearly natural once we defined the need for a very dynamic "single page" application. Our Flex developers found themselves in a known environment (Eclipse) - developing a webapp with a strongly typed language. It took them 2 weeks to learn the GWT Framework - together with the Java language itself! We were delighted to see the number of high quality libraries already available, as well as the vivid community around GWT. Finally, the determination of Google to keep the project updated was a convincing factor for adopting this technology. From the beginning, we started using a MVC framework to keep our code well-structured, and it soon paid itself off in development. The predictability of the framework was a big plus: you write code, you reload, it works. All the bugs we encountered were documented, so finding workarounds was pretty straightforward. We were a bit anxious about legacy Javascript bridging, but JSNI proved to be a very easy way to use 3rd-party libraries. We started development with version 1.5.3 of GWT and we just ported the app to 1.7. The porting process was a breeze and we’re very happy to be able to use the Eclipse plug-in for GWT. I guess one area of departure is that we did not follow the classical RPC way for our server-side interactions. Instead, we built a REST API to keep our back-end services agnostic from the client used. We’re using Restlets to interact with our REST API, which once again worked flawlessly, as expected. Our overall experience using GWT has been very positive. The fact that we develop in Java has a lot of advantages, such as being able to use java debugging tools - instead of just Firebug - if you’re in pure JavaScript. GWT has a few things we would like to see, like being able to load code dynamically instead of compiling everything in a large .js file, but it seems that GWT2.0 will bring forth some new possibilities.
The choice of using GWT was nearly natural once we defined the need for a very dynamic "single page" application.
Our Flex developers found themselves in a known environment (Eclipse) - developing a webapp with a strongly typed language. It took them 2 weeks to learn the GWT Framework - together with the Java language itself!
We were delighted to see the number of high quality libraries already available, as well as the vivid community around GWT. Finally, the determination of Google to keep the project updated was a convincing factor for adopting this technology.
From the beginning, we started using a MVC framework to keep our code well-structured, and it soon paid itself off in development. The predictability of the framework was a big plus: you write code, you reload, it works. All the bugs we encountered were documented, so finding workarounds was pretty straightforward. We were a bit anxious about legacy Javascript bridging, but JSNI proved to be a very easy way to use 3rd-party libraries.
We started development with version 1.5.3 of GWT and we just ported the app to 1.7. The porting process was a breeze and we’re very happy to be able to use the Eclipse plug-in for GWT.
I guess one area of departure is that we did not follow the classical RPC way for our server-side interactions. Instead, we built a REST API to keep our back-end services agnostic from the client used. We’re using Restlets to interact with our REST API, which once again worked flawlessly, as expected.
Our overall experience using GWT has been very positive. The fact that we develop in Java has a lot of advantages, such as being able to use java debugging tools - instead of just Firebug - if you’re in pure JavaScript. GWT has a few things we would like to see, like being able to load code dynamically instead of compiling everything in a large .js file, but it seems that GWT2.0 will bring forth some new possibilities.
Community announcements
GWT-in-the-Air (and in Yahoo! BrowserPlusTM): Thomas Broyer, one of our GWT contributors and a regular on the forum, has been working on the GWT-in-the-Air project over the last year. The project provides an Adobe AIR version of your GWT application, making it ready to run in the browser or on the desktop. Thomas has most recently added support for Yahoo! BrowserPlusTM as well, which allows you to add desktop capabilities to your GWT app.
GChart 2.6 released: John Gunther recently announced the GChart 2.5 release, which adds a GWT canvas rendering option for better looking charts and graphs.GChart 2.6 was also published recently which fixes deprecated event listener calls and other bug fixes. Check out the live demo and examples if you're interested in using it for your own GWT application.
An early look at Spring4Gwt: Dustin Mallory has recently created a new project called spring4gwt, which, as you may have guessed, offers a way to integrate GWT with the Spring framework. The project is still in its early stages, but aims to offer both exported Spring services to the GWT client and DI that works specifically for Spring components.
GWT-cs - Springifying your GWT application code: We've seen integrating with Spring, but what if you wanted to develop your GWT client-side code in a Spring-like fashion? In comes the newly started GWT-cs project for just such a use case. With this library, you can develop your GWT client-side application structure using Spring-like bean configuration in an XML format.
Uploading with GWTUpload: While the FileUpload widget in GWT core provides one part of the key to uploading files in your GWT applications, the server-side component and it's interaction with the client-side form submission is often the part developers get stuck on. Using GWTUpload, you can get file uploads ready in just a few steps. You also get other nifty features like progress bars showing file upload progress (file size, bytes transferred).
New Articles on the GWT homepage
We've recently published new articles on the GWT homepage, including:
These articles were created to address the many inquiries we've seen on integration and testing topics, so hopefully they will be helpful to you if you're at the point of making integration or design decisions in your GWT project. Also, many of these articles were written in collaboration with the GWT developer community, so if you have any articles or topics that you would like us to consider for publishing on the GWT homepage, feel free to get in touch with us.
Normally, a minor update such as this would have been named 1.6.5 (the previous latest version of GWT was 1.6.4), but we did add the value "ie8" to the "user.agent" deferred binding property, which could impact projects using custom deferred binding rules that are sensitive to that property. Thus, we went with GWT 1.7 rather than GWT 1.6.5, to indicate that you may need to pay attention to that change. Details are in the release notes.
In every other respect, this is just a bugfix release, so in the vast majority of cases, the update-recompile process should be nearly effortless.
Download Google Web Toolkit 1.7
Gilead GWT adapter for Google App Engine: Bruno Marchesson, creator of the Gilead (aka Hibernate4GWT) library, has created another adapter - this time for GWT applications running on App Engine. It is still in its early stages, but this may be useful to those looking to build their applications using GWT and Google App Engine and who don't mind hammering on fresh code.
Vaadin 6 (formerly IT Mill Toolkit) releases: The IT Mill team has come out with the latest release of their toolkit built using GWT technology. Vaadin offers a different take on Ajax application development that employs server-driven architecture with widgets composed of both client and server-side components. Their latest release is available on their new site.
SmartGWT out of beta with v1.1 release: Sanjiv Jivan has been hard at work getting the SmartGWT library ready for its out of beta release. It includes many useful new features that you might be interested in checking out.
Google I/O 2009 - Caught on video
GWT at Google I/O: In case you missed it, we've captured all the GWT sessions at Google I/O on video, including the keynote presenting Google Wave (built with GWT).
GWT Developers at Google I/O: A few external developers who use GWT also stopped by I/O and participated in the Developer Sandbox. Despite all the hustle and bustle around the sandbox area, we managed to talk to some of them on video about their development experience. Some of those we talked to include:
We also talked to many other developers using Google Technologies to create some great applications.
A couple months ago, we asked the community to tell us about their GWT applications and their experience developing them. We were greatly pleased to see many responses, and lots of neat applications. In fact, we had so many responses that we needed a better way to showcase and share them with the community.
Introducing the new GWT Application Gallery to save the day, now posted on the GWT homepage. Improving on the earlier GWT Application Gallery, the new gallery adds more features to make community interaction easier and application entries more meaningful. Here are some of these new features that you can look forward to:
We already have a number of entries both from the previous app gallery and newer entries from respondents to our call out a few months ago, and we'd love to hear from you too. So please, check out the new GWT App Gallery to see the kind of great applications the community has been developing, share your opinions through the comments and ratings feature, and add your own applications to the gallery.
As a sidenote, Google I/O is in full swing. In the spirit of sharing applications and development experiences, we've organized a Developer Sandbox area this year where third party developers who have used Google developer products can showcase their applications and talk about how they've created them. If you're attending Google I/O, drop by to check out some of these products live. I'll be around that area as well, so please come by to say hello.
By Eric Ayers, Google Web Toolkit Team
We are pleased to announce updates to the Google API Libraries for the Google Web Toolkit project. The Google API Libraries for GWT project allows GWT developers to access some of Google's popular JavaScript APIs. This release contains new bindings for two libraries:
These libraries each come with sample code and Javadoc documentation.
In addition, other libraries have been updated. Highlights include:
StudyBlue is an academic social networking application, built with GWT, that helps students study smarter, faster. To manage the build process during the development of their application, the StudyBlue team uses the Maven build system. Chris Klundt and Hicham Bouabdallah from StudyBlue have kindly dropped by to share their tips on getting GWT and Maven to play nicely together.
Maven is a great resource that allows developers to enable dependency management within their GWT web applications. While a complete description of Maven's dependency management is beyond the scope of this article, we encourage you to read more here . Essentially, Maven allows you to modularize your GWT project, separating the reusable pieces of code (i.e. Custom Widgets or Data Transfer Objects) into their own projects while maintaining versioning. In addition, Maven allows you to incorporate several different modules without having to write/maintain a complex Ant build file.
When developing your application you may quickly realize that it would be beneficial to separate large pieces into separate modules for easier management and reusability. We have multiple internal applications that use the same Data Transfer Objects and Custom Widgets. In our case, we found that separating these two pieces into separate modules made everyone's life easier. In order to accomplish this, we created two separate Maven modules, studyblue-data and studyblue-widgets.
Your resulting project hierarchy will look like this once its all hooked up:
Each of the new modules (data and widgets) look similar to the main project because they contain a gwt.xml file, however their project structure looks like this:
+ studyblue-data/ + src/ + main/ + java/ + com.studyblue.data/ Data.gwt.xml + com.studyblue.data.client/ Data.java ... + resources/ + test + java/ + resources/ pom.xml
Your Data.gwt.xml file would look like this:
<module> <!-- Inherit the core Web Toolkit stuff. --> <inherits name="'com.google.gwt.user.User'/"> <source path="client"> </module>
Your Data.java file would be empty in most cases:
package com.studyblue.data; import com.google.gwt.core.client.EntryPoint; public class Data implements EntryPoint { public void onModuleLoad() { } }
As per usual, your source code goes under the com.studyblue.data.client package. We created an additional project for studyblue-widgets similar to the one above. At this point, you should have three projects open in your Workspace (your main web app, your newly created data module, and your newly created widget module). Once you've organized your code, it's time to hook it up with your core web application via a few hooks with Maven and the gwt.xml files.
Our studyblue-data pom.xml file looks like the combination of the following:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xsi="http://www.w3.org/2001/XMLSchema-instance" schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelversion>4.0.0</modelversion> <groupid>studyblue</groupid> <artifactid>studyblue-data</artifactid> <version>1.1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>studyblue gwt data</name>
This is the portion that indicates how the jar should be created. The jar's title is "[artifactId]-[version].[packaging]". The parts in red, you would subsitute with your own information. *Note: We use -SNAPSHOT to notify Maven that the jar should be updated on every build (see below).
<repositories> <repository> <id>gwt-maven</id> <url>http://gwt-maven.googlecode.com/svn/trunk/mavenrepo/</url> </repository> </repositories> <!-- include pluginRepository and repository for GWT-Maven --> <pluginrepositories> <pluginrepository> <id>gwt-maven-plugins</id> <url>http://gwt-maven.googlecode.com/svn/trunk/mavenrepo/</url> </pluginrepository> </pluginrepositories>
The repositories tag tells your project where to download the gwt jars (servlet, user, etc). The pluginRepositories tag tells your project where to download the Maven-GWT plugin.
<build> <plugins> <plugin> <artifactid>maven-compiler-plugin</artifactid> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> <plugin> <artifactid>maven-eclipse-plugin</artifactid> <version>2.5.1</version> <configuration> <additionalprojectnatures> <projectnature>org.maven.ide.eclipse.maven2Nature</projectnature> </additionalprojectnatures> <additionalbuildcommands> <buildcommand>org.maven.ide.eclipse.maven2Builder</buildcommand> </additionalbuildcommands> </configuration> </plugin> </plugins> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/client/**</include> <include>**/*.gwt.xml</include> </includes> </resource> </resources> </build>
The build tag tells Maven what Java version you want your jar to be compiled into (1.6 in this case). The resources tag lets your project compiler know which java files should be included in the jar (i.e. ALL YOUR CODE).
<properties> <gwtversion>1.5.3</gwtversion> </properties>
The properties tag allows us to set a variable (gwtVersion) so Maven knows which version of GWT it needs to download when compiling. When it's time to upgrade, just change the version and the rest takes care of itself.
<dependencies> <dependency> <groupid>com.google.gwt</groupid> <artifactid>gwt-user</artifactid> <version>${gwtVersion}</version> <scope>provided</scope> </dependency> </dependencies>
The dependencies tag tells your project which jars you need to compile. In the case of the studyblue-data and studyblue-widgets modules, we reference the GWT user jar, so we need to include it. Notice it takes use of the gwtVersion variable. There are six different types of scope. The three most important are "runtime", "provided" and "compile". Runtime means "I don't need it during compilation of the jar, but I do need it when the jar is executed." Provided means "The project that depends on this module will provide the jar". Compile means "This module needs the jar immediately for compilation".
In this case, we plan on connecting the studyblue-data and studyblue-widget modules to our main web app, which will "provide" the necessary GWT jars for these modules.
<dependency> <groupid>studyblue</groupid> <artifactid>studyblue-data</artifactid> <version>1.1.0-SNAPSHOT</version> <scope>compile</scope> </dependency>
If one module needs to reference an additional module (i.e. studyblue-widgets depends on studyblue-data), you could insert the above code into studyblue-widget dependencies.
</project>
Don't forget to close your project tag :) Make sure you generate the appropriate pom.xml for your widgets module as well.
Alright, so you've separated your data and widgets from your main app. You built two projects and included a pom.xml file in each. Now it's time to build studyblue-data and studyblue-widgets into jars so you (and your teammates) can use them as necessary.
This part is super easy, just open command prompt or terminal and navigate to the project's root folder. Type the following:
mvn clean deploy
That's it. Your project will be compiled with all the necessary libraries and is available for consumption by you and your teammates under the title entered above (studyblue-data-1.1.0-SNAPSHOT.jar and studyblue-widget-1.1.0-SNAPSHOT.jar).
So, you now have the two jars available, and you could just simply add them to your main web app's classpath. However, if you enable Maven on your main web app, you'll be able to take advantage of Maven's dependency management. This way you'll be able to download updated jars instantly and automatically. Additionally, assuming your main web app project is Mavenized you can include the GWT jar dependencies (servlet, user, etc) in the web app automatically.
To do this, you need to insert the following into your main web apps pom.xml below the properties tag:
<profiles> <profile> <id>gwt-dev-windows</id> <properties> <platform>windows</platform> </properties> <activation> <activebydefault>true</activebydefault> <os> <family>Windows</family> </os> </activation> </profile> <profile> <id>gwt-dev-mac</id> <properties> <platform>mac</platform> </properties> <activation> <os> <family>mac</family> </os> </activation> </profile> <profile> <id>gwt-dev-linux</id> <properties> <platform>linux</platform> </properties> <activation> <os> <name>Linux</name> </os> </activation> </profile> </profiles>
The profiles tag allows our developers to use whichever GWT jars are necessary for their operating system (takes care of Windows vs. Mac vs. Linux automatically :) ). No more keeping copies of all GWT jars and native libraries in your project folder.
Finally, modify the dependencies section to look like this:
<dependencies> <dependency> <groupid>com.google.gwt</groupid> <artifactid>gwt-servlet</artifactid> <version>${gwtVersion}</version> <scope>runtime</scope> </dependency> <dependency> <groupid>com.google.gwt</groupid> <artifactid>gwt-user</artifactid> <version>${gwtVersion}</version> <scope>compile</scope> </dependency> <dependency> <groupid>com.google.gwt</groupid> <artifactid>gwt-dev</artifactid> <version>${gwtVersion}</version> <classifier>${platform}-libs</classifier> <type>zip</type> <scope>compile</scope> </dependency> <dependency> <groupid>com.google.gwt</groupid> <artifactid>gwt-dev</artifactid> <version>${gwtVersion}</version> <classifier>${platform}</classifier> <scope>compile</scope> </dependency> <dependency> <groupid>studyblue</groupid> <artifactid>studyblue-data</artifactid> <version>1.1.0-SNAPSHOT</version> <scope>compile</scope> </dependency> <dependency> <groupid>studyblue</groupid> <artifactid>studyblue-widgets</artifactid> <version>1.1.0-SNAPSHOT</version> <scope>compile</scope> </dependency> </dependencies>
Notice here that the <scope> for the GWT jars is "compile", which ensures they are downloaded during compilation of the web app and "provided" to the dependent modules studyblue-data and studyblue-widgets. The GWT servlet jar is only needed when the web app is executed, so we choose "runtime" here.
Don't forget your gwt.xml
In order to make sure that our main web app knows about studyblue-data and studyblue-widgets we have to include the following lines in our main app's gwt.xml file:
<inherits name='com.studyblue.data.Data' /> <inherits name='com.studyblue.widgets.Widgets' />
Reflecting Updates In Your Modules
During development, we want our main web app to reflect changes that we make in the modules (studyblue-data and studyblue-widgets), everytime we build the project. This way every developer who is working on a project that references the modules (including our main web app), can get the latest build of the jars. We use the Maven keyword "-SNAPSHOT" when versioning our modules during development (i.e. studyblue-data-1.1.0-SNAPSHOT). Snapshot is a special version that indicates a current development copy. With a SNAPSHOT version, Maven will automatically fetch the latest SNAPSHOT every time you build your project. For rapidly moving code, this can be a necessity, particularly in a team environment. When you are ready to release the code, you finalize the version by removing "-SNAPSHOT".
To update your SNAPSHOTS before executing hosted mode or compilation, run this command in your project's root directory:
mvn clean --update-snapshots
Running Hosted Mode and Compiling
As long as your Maven dependencies are added to your project's classpath, you can execute hosted mode and GWT-Compile without worry. At StudyBlue, we use the Maven plugin for Eclipse (http://m2eclipse.sonatype.org/update/ ) to add all our Maven dependencies to our classpath, update snapshots and for editing the pom.xml files.
Maven can be tricky to setup, but once you've got it connected to your GWT project, you'll be amazed at how efficient and modular your application can become.