Blog de Salvador Diaz

Keep your source tree clean ! Maven workarounds for GWT 1.6

par salvador le Apr.29, 2009, sous GWT, maven

In this series of posts I’ll analyze the current conflicts between the new Google Eclipse Plugin (also know as GEP), maven and the gwt-maven-plugin. Once these conflicts are identified, I’ll try to find workarounds and advice on what possible perennial solutions could be implemented by each team. This first post is directed at the impatient crowd, the ones looking for a copy-paste solution (you do know that’s bad practice, don’t you ?) so I’ll be as brief as I can and give as little detail as I can to get you started using GWT with Eclipse, the Google Eclipse Plugin and the gwt-maven-plugin. For those of you who don’t mind reading long posts and want to understand exactly what’s keeping these 4 tools from working together and how I came up with the workarounds explained here, check back soon(ish), the following posts will be a lot more detailed.

Introduction

The Google Web Toolkit team announced the release of GWT 1.6.4 a couple of weeks ago (for those keeping track, that’s roughly 6 months after the 1.5.3 release and 13 months after the 1.4 release). I’m not going to describe here at length the improvements brought by this new version, you can read all about it in the release notes and the new and improved developer documentation. Instead I’m going to focus on one of the changes that has caused a great deal of frustration to us GWT developers relying on maven to automate the build process: the new war project structure.

So what’s the problem with the new project structure ? If you use GWT for a personal project and you’re the only person modifying your source you should be fine because it’s relatively trivial to keep your source files separated from generated files. The problem really arises when your project is shared between a whole team (typically on a version control system): in that case you’ll really want to keep your original source and resources files separated from generated files and that’s precisely the problem with the new GWT project structure, it assumes that server-side library dependencies must be copied into /war/WEB-INF/lib and that the java compiler outputs to /war/WEB-INF/classes (thus polluting the war folder).

The solution

How do you configure Eclipse, maven and the gwt-maven-plugin to work with GWT 1.6.4 then ? I’ll start from scratch with the archetype from the gwt-maven-plugin-1.1-SNAPSHOT and I’ll guide you step by step in the pom and eclipse configuration. In the end, you’ll be able to develop your GWT application with Eclipse, taking advantage of the hosted mode for debugging, you’ll have a clean source tree, and you’ll be able to package your application as a war. Unfortunately, I still haven’t found a way to launch as a Google Web Application (the custom launcher provided by the GEP) and the warnings about unavailable classes in client-side code don’t seem to be working, effectively making the GEP almost useless. Fortunately the hosted mode will warn you about unavailable client-side classes and we don’t need the GEP to launch the hosted mode so pretty much all of the GEP functionality is there, only without the GEP.

So without further ado, here’s what you need to run and develop GWT applications with Eclipse, maven and the Google Eclipse Plugin (ok that last one doesn’t do anything useful yet in this configuration, but at least it can be activated).

Prerequisites

Project creation with gwt-maven-plugin

  • To create a GWT project with the gwt-maven-plugin, just open a command line, change the working directory to the location where you want to create your project (typically the location of your eclipse workspace) and type the following command. You’ll end up with a folder called “maven-example”
  • Fire up Eclipse and import the project we just created (”File” > “Import” > “Maven projects” > “Browse” and browse to the “maven-example” folder and click “Finish”).
    Importing the created project into the workspace

    Importing the created project into the workspace

    You’ll end up with a project which looks like this in your workspace.

    Project structure

    Project structure

POM configuration (maven build configuration)

  • Open the pom.xml file, it will look like this. Modify it to look like this.

GWT module tweak

  • Add a rename-to attribute to the GWT module declaration file.
  • Change the Application.html file to look like this. Move that file to the src/main/webapp folder.
  • Delete the file named index.html located in the src/main/webapp folder.
  • Open the web.xml file located in src/main/webapp/WEB-INF and change the value of the welcome-file to Application.html.

m2eclipse plugin configuration

  • Global configuration (”Window > Preferences > Maven” or “Command+,”): no goals should be executed neither on project import nor when updating project configuration.

    Global m2eclipse configuration

    Global m2eclipse configuration

  • Project-level configuration (Right click on project > Properties > Maven): clean compile goals on project clean and on resources change compile on resources change.

    Project-level m2eclipse configuration

    Project-level m2eclipse configuration

Eclipse project configuration

  • Check the “Allow output folders for source folders” option in the “Java Build Path” panel under the “Project Properties” dialog.
  • Change output folders for src/main/java, src/main/resources and “Default output folder” to maven-example/target/gwt/WEB-INF/classes. Updating project configuration in m2eclipse context menu option should do it automatically.

    Modified Java Build Path

    Modified Java Build Path

  • Create a launcher for hosted mode debugging (Open the “Debug configurations” dialog in the “Run” menu): click the links for screenshots of the “Main” tab, the “Arguments” tab, the “Classpath” tab and the steps to add folders and external jars to the classpath (note that the gwt-dev jar name depends on your OS).

The results

The end result is a working GWT project with the following characteristics:

  • Can be developed (code - debug - compile) entirely in Eclipse (hosted mode works fine for compiling and debugging) just like with the GEP.
  • Can be packaged automatically by maven (type mvn package to get a war in the target directory).
  • The source tree is completely separated from generated artifacts, allowing for an easiest experience for developers working with VCSs.
  • Follows maven conventions (and everybody knows that conventions are good).

What you don’t get:

  • Google App Engine application development (outside the scope of this guide).
  • Warnings about unavailable classes in client-side GWT code (You’ll get them on the hosted mode console though).
  • Right-click > Run as Google Web Application (Google’s fancy launchers don’t seem to like the separation between sources and resources so they won’t launch our application)

I think it’s a pretty good compromise if you’re looking forward to use GWT 1.6 in a maven environment, pretty much all of the functionality of GEP is there AND you are following the maven way. There are a few strange behaviors in some corner cases, so come back later for the follow-up to this post where I’ll explain in detail how I found this workarounds, how these tools work together and how to troubleshoot any problems that you’ll be kind enough to report in the comments.

Edit 1 (03/may/2009):

Thanks to Eugene Kuleshov for his contribution (see first comment). The Eclipse buildpath configuration is now automatically handled by m2eclipse.

If you tried this tutorial before this edit, you should have spotted a bug in m2eclipse that stopped the copy-resources goal from the maven-resources-plugin from working. Try the latest version of the pom and make sure the project level configuration for m2eclipse is correct (check the screenshot).

Update 2 (october 5th 2009):

I haven’t had the time to fully update this tutorial, but from what I can read in the comments, this should also work with GWT 1.7 (do read the comments if you’re attempting to get it working).

Update 3 (october 23th 2009):

As the last commenters noted, all the screenshots are dead, I thought it’d be more reliable to store them on bayimg.com than in my own server but they proved me wrong. I’ll try to reupload them this weekend but in the meantime you can download a zip with all the screenshots by clicking here.

:, , , , ,
43 commentaires pour ce post:
  1. Eugene Kuleshov

    You can change the default output folder used by Maven from target/classes to target/gwt/WEB-INF/classes in the pom.xml using build/outputDirectory element. In a form-based pom editor provided by m2eclipse it is the “Output” filed located on Build tab.

  2. nicolas de loof

    Just a note on the eclipse lauch configuration : it can be generated by the gwt-maven-plugin using “mvn gwt:eclipse”. This will also put all necessary libs in webapp WEB-ING/lib if not allready done.

    Your setup looks good but use the same webapp structure for hosted mode and target WAR. This may not be desirable if your server-side code is more than just few servelts : hosted mode is designed for quick and lightweigh devs, for real server testing use the -noserver option.

  3. Lakech

    Hi,

    I tried the exclusion to avoid the GWT issue 3439 with :

    javax/servlet/**

    But the javax class are in my war…

    I avoid this with a ant run delete but i would prefer to use the exclusion solution.

    Any idea ?

  4. Malte

    Thanks for this howto, but I found a fault in the gwt-maven-plugin configuration part. The runTarget parameter is missing and has to be set to Application/Application.html.

    Greetz
    Malte

  5. salvador

    @nicolas
    Generating the run target with gwt-maven-plugin would be the ideal solution, however I think there’s a bug that causes gwt:eclipse to generate an incorrect run target under certain circumstances. Is it solved yet ? As for the -notarget option, we have several large GWT projects and launching like I described in my post doesn’t feel sluggish or anything. Plus there are some downsides to running with the -noserver option that I’ll mention in my next post.

    @Lakech
    I haven’t yet been bitten by this particular bug (we haven’t migrated our GWT projects to 1.6 yet) so I can’t really answer right now. I’ll try to address this in my next post.


    @Malte

    the runTarget parameter is only needed for the goal gwt:run or gwt:debug. In this tutorial I don’t use those goals, instead I use the eclipse launcher, that’s why I didn’t configure the runTarget.
    I’ll talk about all of the goals available in gwt-maven-plugin in one of my next posts, so check back soon.

  6. KaffeineComa

    Merci bien, ça marche!

  7. limbicsystem

    Hmm, not working for me. It seems to not be creating any war directory (is it supposed to do that under target?) Why are you giving a “-war .” argument? Shouldn’t it be “-war target/SOMETHING” ?

    Anyway, thanks for taking this problem up.. it has been seriously neglected by Google, IMHO.

  8. salvador

    @KaffeineComa
    De rien ! Je suis content que ça marche.

    @limbicsystem
    The war directory under target is called gwt. If it’s not creating it, you might want to double check your m2eclipse settings (is “Skip maven compiler …” unchecked ?). As for the argument “-war .” : it is relative to the working directory so that translates to “-war target/gwt

  9. limbicsystem

    It creates the target/gwt directory, it’s just that that directory seems to not be the “current” directory when the config is run. I have to use “-war target/gwt”, and then it works. Why is target/gwt the current-working-directory in your setup? I don’t see why that should be so.

  10. nicolas de loof

    The gwt:eclipse goal has no way to detect the startupUrl based on gwt modules in the webapp (or maybe you’ve got a suggestion ?). The generated launch configuration file are just a helper the user can edit to set it’s own config.

    I still have to check MGWT-29. Testcases and patches are welcome ;)

  11. Dennis

    Thank you for this great tutorial!

    I do though have one newbish question. When I run the debug configuration I get the following error:

    [ERROR] Unable to find ‘Application/html.gwt.xml’ on your classpath; could be a typo, or maybe you forgot to include a classpath entry for source?

    If I change the -startupURL Application.html to -startupURL Application it seems the filename is correct but it still does not compile.

    What am I doing wrong?

  12. salvador

    @Dennis
    That’s a tough question to answer without further details. Fortunately for you I helped somebody who was having the same problem this morning and it turns out that his -war parameter was wrong. Make sure you didn’t forget the dot after it. It must read -war .

  13. javapda

    Thank you for the great post!

    I have been able to run the application and debug using maven.

    Does this build the test objects?
    When I rename GwtTestSample to GwtTestSampleTest and then run a mvn test there are failures in that it cannot find the compiled test classes.

    Thanks again

  14. Dennis

    Thank you so much! That was exactly the problem.

  15. Anthony

    Hello,

    Thank your for this tutorial.

    I had the same problem than Dennis and your response helped me to correct it.
    Meanwhile, I have nom a new similar error when I run the debug configuration :
    [ERROR] Unable to find ‘fr/salvadoriaz/gwt/sample/Application.gwt.xml’ on your classpath; could be a typo, or maybe you forgot to include a classpath entry for source?

    Can you help me ?

    Thanks.

  16. Anthony

    Sorry for my precedent post !!
    I think I have made a mistake in my debug configuration.
    It’s working now.

    Thanks a lot

  17. Petit

    Hi,

    I think you should note on your tutorial that you should use “-war .” on the launcher configuration and emphasis on the dot.
    I just lost 2h figuring out that this tiny little dot was not a dead pixel or a dust on my Hd screen.

    Thanks for the tutorial.

    Chris

  18. limbicsystem

    I had this setup happily working for a week or so, then yesterday it mysteriously started failing about 75% of the time on our build server. It turns out that the gwt-maven-plugin does not always respect the config param. This was maddening, because it seems to work some of the time, depending on what happens to be in your plugins cache (and perhaps the phase of the moon.)

    We have it working reliable now after changing this to , as documented in the plugin web site:
    http://mojo.codehaus.org/gwt-maven-plugin/1.1-SNAPSHOT/compile-mojo.html

  19. Jay Kang

    Great article!! I’m not using GWT 1.6.4 at the moment, but really appreciated the in depth description of the setup process. <3 pictures. I’m awaiting for your next post, hope it’s on multi-project layout!

  20. matt

    Does anybody have a clue how to include other artifacts where classes and source are in separate JARs? m2eclipse doesn’t seem to honor the sources attribute when updating the project configuration. Thanks!

  21. rl

    Thanks for the useful article. I am having trouble when I do a mvn clean package. I am getting the following error and I’m not sure where the problem is.

    It seems like /target/gwt/myapp IS NOT created but /target/test-project-1.0-SNAPSHOT/myapp IS created. As a result, when Maven tries to copy it fails with this error:

    [INFO] [resources:testResources]
    [INFO] Using ‘UTF-8′ encoding to copy filtered resources.
    [INFO] skip non existing resourceDirectory c:\src\test-project\src\test\resources
    [INFO] [compiler:testCompile]
    [INFO] Nothing to compile - all classes are up to date
    [INFO] [surefire:test]
    [INFO] No tests to run.
    [INFO] [war:war]
    [INFO] Packaging webapp
    [INFO] Assembling webapp[test-project] in [c:\src\test-project\target\test-project-1.0-SNAPSHOT]
    [INFO] Processing war project
    [INFO] Copying webapp webResources[c:\src\test-project/target/gwt/myapp] to[c:\src\test-project\target\test-project-1.0-SNAPSHOT]
    [INFO] ————————————————————————
    [ERROR] FATAL ERROR
    [INFO] ————————————————————————
    [INFO] basedir c:\src\test-project\target\gwt\myapp does not exist
    [INFO] ————————————————————————
    [INFO] Trace
    java.lang.IllegalStateException: basedir c:\src\test-project\target\gwt\myapp does not exist
    at org.codehaus.plexus.util.DirectoryScanner.scan(DirectoryScanner.java:550)

    What should I look at? I reviewed the pom.xml here against mine and the Eclipse screenshots but haven’t pinpointed the issue.

  22. rl

    BTW - Looks like this blog stripped out the XML tags in my comment above.

    I believe this article uses the configuration parameters for the OLD gwt-maven-plugin from Google code BUT uses the NEW plugin from Codehaus. Can someone elaborate on this discrepancy? Seems like the pom should use the NEW parameters.

    OLD:

    http://gwt-maven.googlecode.com/svn/docs/maven-googlewebtoolkit2-plugin/compile-mojo.html

    (has “output” has a config parameter)
    output

    Location on filesystem where GWT will write output files (-out option to GWTCompiler).

    * Type: java.io.File
    * Required: No
    * Expression: ${project.build.directory}/${project.build.finalName}

    NEW:
    http://mojo.codehaus.org/gwt-maven-plugin/1.1-SNAPSHOT/compile-mojo.html

    webappDirectory:
    Location on filesystem where GWT will write output files (-out option to GWTCompiler).

    * Type: java.io.File
    * Required: No
    * Expression: ${gwt.war}
    * Default: ${project.build.directory}/${project.build.finalName}

    AND has a REQUIRED parameter:

    generateDirectory:
    Folder where generated-source will be created (automatically added to compile classpath).

    * Type: java.io.File
    * Required: Yes
    * Default: ${project.build.directory}/generated-sources/gwt

  23. salvador

    Well, since the SNAPSHOT version is a moving target I’m not sure it hasn’t changed since I wrote this tutorial. I’ll be sure to check it and update the article.

  24. mariusz.pala

    I agree, “output” tag should be replaced with “webappDirectory”, otherwise package doesn’t work.
    Also to avoid stack overflow exception you can add
    extraJvmArgs tag: -Xmx512m -Xss1024k

  25. Jason

    @rl i ran into the same problem, i thought i was doing something wrong. salvador is there a fix for this?

    this tutorial has been a great help!

    jason

  26. Aaron Digulla

    @rl: The fatal error is because of the webResources path in the maven-war-plugin. Replace

    ${gwt.output.directory}/${gwt.module.alias}

    with

    ${basedir}/target/${project.name}-${project.version}/${gwt.module.alias}

    and the error goes away.

    As to the rest of the article, here are my comments:

    #1: Don’t *ever* add “compile” to the Maven Project-level configuration. Never. Never. Ever! This will seriously confuse the Eclipse IDE and you’ll suddenly get errors that classes can’t be found which are obviously there (F3/”Open Declaration” can find them, but the Java compiler can’t).

    #2: Change the order of the GWT dependencies. Make sure that “gwt-user” comes first. This way, you will have the GWT sources for debugging. Note that this only works with the latest version m2eclipse which honors the order of the dependencies in the pom.xml.

    As I said above, the latest version of the gwt-maven-plugin seems to have changed the paths where it will write the results of the compile step.

    #3 If GWT hostes mode complains that it can’t find the sources, open the “Run Configuration”, select your launch config, open the tab “Classpath” and make sure that the source folders are correct.

    For some reason, Eclipse 3.5 won’t let you edit this field. You have to open the launch XML file and fix the path manually. Look for a “internalArchive”.

    #4 Some comments about Eclipse 3.5: Yes, it works with the latest m2eclipse. You can’t use the GWT plugin, yet, but you can import a project created with the command line tools of GWT 1.6, enabling Maven2 and then making all the changes outlined here.

  27. rl

    Salvador - Can you update the pom.xml in this article to work with the 1.1 release of the plug in and incorporate the changes discussed in the comments. That would be a big help! thanks! merci!

  28. rl

    Aaron,

    I’m not sure what to after reading your statement:

    “#1: Don’t *ever* add “compile” to the Maven Project-level configuration. Never. Never. Ever! This will seriously confuse the Eclipse IDE and you’ll suddenly get errors that classes can’t be found which are obviously there (F3/”Open Declaration” can find them, but the Java compiler can’t).”

    I have the following code defined for the plugin:

    http://pastebin.ca/1473104

    What changes do I need to make?

  29. rl

    Can someone post an up-to-date working pom.xml? The one in this article has issues.

    BTW - I noticed that several comments are missing from this blog. Was there a server crash?

  30. gamUssA

    @rl
    pom.xml which works fine for me http://dumpz.org/10234/

  31. gAmUssA

    @rl
    pom.xml which works fine for me http://dumpz.org/10234/

    for Eclipse 3.5 works fine too.

  32. Pepe

    Is it just me or does the gwt-maven-plugin documentation really suck compare to gwt-maven plugin hosted at Google?

  33. Diogo

    Great post Salvador, it’s very helpful…

    Thanks.

  34. Dennis

    Is it possible to somehow not create the Eclipse project configuration manually e.g have it created automatically in the POM for instance? It would be great for when other people in my team checkout the project e.g. so they could just checkout the project from SVN and it would run “out of the box”.

    PS. Thanks for the great tutorial!

  35. picosam

    Thank you, I confirm that this works with GWT 1.7 and Eclipse 3.5; will keep you posted if there are any “breaks”, and I would love to hear about any improvements that you would achieve!

    Merci, je confirme que cela marche avec GWT 1.7 et Eclipse 3.5; je vous tiens au courant s’il y a des irrégularités, et j’aimerais savoir si vous faisiez des avancement sur le sujet !

  36. baguee

    Great job! Thanks a lot! (GWT 1.7, Eclipse 3.5)

  37. Judge

    The problem ocurred when I wanted to add spring security to my app. Here’s the problem: Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/security]
    Offending resource: class path resource [applicationContext-security.xml]

    Any ideas?

  38. ram

    Great tutorial. Good work salvador, but the images are missing.

  39. mohammad riaz

    This is a good tutorial for gwt and maven integration.
    I see the configuration images for “Main” tab, the “Arguments” tab, the “Classpath” tab are not loaded.

    Salvador, can you please zip the images so that we can download the zip.

  40. mohammad riaz

    Thanks Salvador. You are real quick in helping.
    Now the downloadable zip consists the screenshots
    of the dead image links.

  41. Jon

    I am trying to execute this step by step, and cannot get past the command line step to create the project. I think something has changed since this was posted:

    “BUILD FAILURE”
    “The desired archetype does not exist (org.apache.maven.archetypes:gwt-maven-plugn:1.1-SNAPSHOT)”

  42. salvador

    @Jon:

    I don’t know if it changed, I haven’t had time to fully update the tutorial since I wrote it, and for that I’m really sorry.

    That being said, you might want to check the plugin usage instructions, and specifically the archetype generation instructions.

    Hope that helps !

Laisser un commentaire

Vous cherchez quelque chose?

Utilisez le formulaire ci-dessous pour lancer une recherche sur le site:

Sites recommandés

Quelques sites pour approfondir les sujets abordés dans mon blog:

Archives

Tous les posts, en ordre chronologique...