gwt-maven-archetypes multiple project setup

242 views
Skip to first unread message

William Davis

unread,
Jul 23, 2015, 1:34:46 PM7/23/15
to Google Web Toolkit
I am using the gwt-maven-archetypes with artifactId modular-webapp by Thomas, which is working excellently. 

However I am trying to make things a little more modular which is causing me difficulty. 
Lets say I have a core gwt app called "core-app", it has been created with the archetype and is working great. 

Now lets say I want to create several specific versions using the core functionality. 
Is it possible for me to create "core-app-module1" and depend on the "core-app". 
Are there any maven tricks that would allow me to depend on and use the core project as a dependency in a sub project?

Thanks,
Will

Thomas Broyer

unread,
Jul 23, 2015, 3:58:16 PM7/23/15
to Google Web Toolkit, wallac...@gmail.com
If it's reusable then it's a gwt-lib, not a gwt-app. Next, create any number of gwt-app depending on the gwt-lib, even possibly one with just a simple EntryPoint and module.gwt.xml, and no customization.

William Davis

unread,
Jul 24, 2015, 8:33:22 AM7/24/15
to Google Web Toolkit, t.br...@gmail.com
Will the gwt-lib projects work with incremental compile or will I have to stop the dev mode, rebuild the library, and run again?

Thomas Broyer

unread,
Jul 24, 2015, 8:44:13 AM7/24/15
to Google Web Toolkit, wallac...@gmail.com, wallac...@gmail.com


On Friday, July 24, 2015 at 2:33:22 PM UTC+2, William Davis wrote:
Will the gwt-lib projects work with incremental compile or will I have to stop the dev mode, rebuild the library, and run again?

One of the goals of net.ltgt.gwt.maven:gwt-maven-plugin was to properly support multimodule projects, and "properly support" includes not having to stop and restart devmode/codeserver when making changes in any module of the reactor (and without hacks and/or profiles in your POMs).

William Davis

unread,
Jul 24, 2015, 9:06:22 AM7/24/15
to Google Web Toolkit, t.br...@gmail.com
That is great news! I hope I can get your much appreciated assistance to help me figure out what I am doing wrong, because as of right now it isn't working for me. I am sure there is something I haven't configured properly so let me show you what I have.

I am using the modular-webapp for the project with gwt-app. Similarly I wanted to have a library project that is divided by client, shared, and server projects. 

So my library set up is as follows:

Each one of those projects uses

<packaging>gwt-lib</packaging>

<build>

<plugins>

<plugin>

<groupId>net.ltgt.gwt.maven</groupId>

<artifactId>gwt-maven-plugin</artifactId>

<version>1.0-rc-2</version>

<extensions>true</extensions>

<configuration>

<moduleName>gwt.library.core.LibraryClient</moduleName>

<moduleShortName>LibraryClient</moduleShortName>

</configuration>

</plugin>

</plugins>

</build>


Of course the module name is different for the shared and server projects. So when I maven install the parent "library-core" project it will compile all 3 sub projects into their respective jars.


Now I created a "base" project that depends on the library. This project was created with the modular-webapp archetype. In my base-client I depend on the library-core-client and my base-server depends on the library-core-server.

For example in the base-client I have this:

<dependency>

<groupId>gwt.library</groupId>

<artifactId>library-core-client</artifactId>

<version>1.0.0-SNAPSHOT</version>

<type>gwt-lib</type>

</dependency>

 


So when I run superdev like this:

gwt:codeserver -pl *-client -am

tomcat7:run -pl *-server -am -Denv=dev


it all works, the dependencies play nice together, the only problem is if I change code in the library-core-client and refresh the browser, it does not detect the change.


Am I missing something or is there a better way to structure the projects so they will work correctly?


Thank you so much,

Will

William Davis

unread,
Jul 24, 2015, 10:13:45 AM7/24/15
to Google Web Toolkit, t.br...@gmail.com, wallac...@gmail.com
I think I figured something out. In the "base" project, in the parent pom, I only defined the three modules in that project like this:
<modules>
    <module>base-client</module>
    <module>base-shared</module>
    <module>base-server</module>
  </modules>

but I changed it to add the client library like this:
<modules>
    <module>base-client</module>
    <module>../library-core/library-core-client</module>
    <module>base-shared</module>
    <module>base-server</module>
  </modules>

and now the incremental compile works when I make changes to the library client.
Is this the correct/best way to do this?

Thanks,
Will

Thomas Broyer

unread,
Jul 24, 2015, 10:31:51 AM7/24/15
to Google Web Toolkit, wallac...@gmail.com, wallac...@gmail.com


On Friday, July 24, 2015 at 3:06:22 PM UTC+2, William Davis wrote:
That is great news! I hope I can get your much appreciated assistance to help me figure out what I am doing wrong, because as of right now it isn't working for me. I am sure there is something I haven't configured properly so let me show you what I have.

I am using the modular-webapp for the project with gwt-app. Similarly I wanted to have a library project that is divided by client, shared, and server projects. 

So my library set up is as follows:

Each one of those projects uses

<packaging>gwt-lib</packaging>

<build>

<plugins>

<plugin>

<groupId>net.ltgt.gwt.maven</groupId>

<artifactId>gwt-maven-plugin</artifactId>

<version>1.0-rc-2</version>

<extensions>true</extensions>

<configuration>

<moduleName>gwt.library.core.LibraryClient</moduleName>

<moduleShortName>LibraryClient</moduleShortName>

</configuration>

</plugin>

</plugins>

</build>


Of course the module name is different for the shared and server projects. So when I maven install the parent "library-core" project it will compile all 3 sub projects into their respective jars.


Only the "client" should be a gwt-lib, and it should then depend on "shared" both without classifier and with classifier=sources (just like how the gwt-app in the archetypes depends on "shared")
(and the "shared" lib should package its sources, again just like the "shared" lib in the archetypes).

Thomas Broyer

unread,
Jul 24, 2015, 10:42:19 AM7/24/15
to Google Web Toolkit, wallac...@gmail.com, wallac...@gmail.com


On Friday, July 24, 2015 at 4:13:45 PM UTC+2, William Davis wrote:
I think I figured something out. In the "base" project, in the parent pom, I only defined the three modules in that project like this:
<modules>
    <module>base-client</module>
    <module>base-shared</module>
    <module>base-server</module>
  </modules>

but I changed it to add the client library like this:
<modules>
    <module>base-client</module>
    <module>../library-core/library-core-client</module>
    <module>base-shared</module>
    <module>base-server</module>
  </modules>

and now the incremental compile works when I make changes to the library client.
Is this the correct/best way to do this?

With your initial setup, the library-core-client (and its transitive dependencies) come from your local repository, and you have to "mvn install" the library each time you make a change to it.
With your final setup, it's all one reactor project (you should include the library-core-shared and library-core-server too BTW), so the gwt-maven-plugin will look at the MavenProject from the reactor build to get its sources.

Your initial setup is OK if you intend to release library-core-* separately from the "base" webapp.
Your final setup is OK if you intend to release everything at once. I'd have rather put everything inside one big project with many submodules (organized into subfolders), but in the end it's up to you to decide.
Note that there's a way to get things working with your initial "2 separate projects" approach though: create a POM file somewhere that lists all modules as submodules (note: you can just list the 2 root modules of your 2 projects and thus get the submodules recursively) and from which one you can run the tomcat7:run and gwt:codeserver goals.

This is all "standard Maven", independent of the gwt-maven-plugin (you'd get the same behavior for server-side code with the tomcat-maven-plugin, not seeing changes to your library-core-shared and library-core-server until you "mvn install" them and restart Tomcat).

William Davis

unread,
Jul 28, 2015, 10:27:34 AM7/28/15
to Google Web Toolkit, t.br...@gmail.com
So the good news is that everything is running well, the incremental compile is working for all the libraries client and server side. I am very impressed with the plugin Thomas.

One last question, what is the correct way to package the whole app into a war for production. I tried to run gwt:package-app on the parent project, the one containing the client, shared, and server projects in the modular-webapp archetype, however when I put the war on tomcat it didn't work. Should I install the projects and libraries in a certain order? What am I doing wrong?

Once again, great work Thomas, this is really excellent.
Thanks for the help,
Will

William Davis

unread,
Jul 29, 2015, 8:52:57 AM7/29/15
to Google Web Toolkit, t.br...@gmail.com, wallac...@gmail.com
So I figured out that if I do a maven install a war is generated in the server project, however my servlet classes from the libraries were not copied into the war. Still looking into that...

William Davis

unread,
Jul 29, 2015, 9:41:05 AM7/29/15
to Google Web Toolkit, t.br...@gmail.com, wallac...@gmail.com
It is probably something simple but what do I need to do to get maven to put the jars of the libraries into the target/[app_name]/WEB-INF/lib directory, for building the war?

William Davis

unread,
Jul 29, 2015, 10:05:24 AM7/29/15
to Google Web Toolkit, t.br...@gmail.com, wallac...@gmail.com
So I found a solution, but I am a little unclear why it works and what is the best practice. Before when it wasn't working I had this dependency in my server project:
<dependency>
     <groupId>com.gwt.library</groupId>
     <artifactId>library-core-server</artifactId>
     <version>1.0.0-SNAPSHOT</version>
     <type>gwt-lib</type>
</dependency>

When I removed the <type>gwt-lib</type> and rebuilt, it put the library-core-server.jar in the web-inf/lib directory which was put in the war and that made it work when I deployed the war.

Am I incorrectly using the  <type>gwt-lib</type>?
Is there a better way to make sure that jar gets put in the war?
Will anything not work correctly if I don't put in the  <type>gwt-lib</type>?

Thanks,
Will

Thomas Broyer

unread,
Jul 29, 2015, 11:21:04 AM7/29/15
to Google Web Toolkit, wallac...@gmail.com, wallac...@gmail.com


On Wednesday, July 29, 2015 at 4:05:24 PM UTC+2, William Davis wrote:
So I found a solution, but I am a little unclear why it works and what is the best practice. Before when it wasn't working I had this dependency in my server project:
<dependency>
     <groupId>com.gwt.library</groupId>
     <artifactId>library-core-server</artifactId>
     <version>1.0.0-SNAPSHOT</version>
     <type>gwt-lib</type>
</dependency>

When I removed the <type>gwt-lib</type> and rebuilt, it put the library-core-server.jar in the web-inf/lib directory which was put in the war and that made it work when I deployed the war.

Am I incorrectly using the  <type>gwt-lib</type>?

Yes.
gwt-lib is for client-side JARs where the sources are also packaged inside the JAR.
Rule of thumb: you should only use <type>gwt-lib</type> in POMs with <packaging>gwt-lib</packaging> or <packaging>gwt-war</packaging>, there's no reason to use them anywhere else (unless you use the gwt-maven-plugin without the gwt-lib/gwt-app lifecycles)
 
Is there a better way to make sure that jar gets put in the war?

No. The proper way to declare server-side dependencies is to use <type>jar</type> (or omit the <type> as "jar" is the default)
 
Will anything not work correctly if I don't put in the  <type>gwt-lib</type>?

For server-side modules, no.

Thomas Broyer

unread,
Jul 29, 2015, 11:22:25 AM7/29/15
to Google Web Toolkit, wallac...@gmail.com, wallac...@gmail.com


On Wednesday, July 29, 2015 at 2:52:57 PM UTC+2, William Davis wrote:
So I figured out that if I do a maven install a war is generated in the server project, however my servlet classes from the libraries were not copied into the war. Still looking into that...

"'mvn install' is an antipattern". 'mvn package' (or 'mvn verify' to also run integration tests) will work the same (without the "install' side-effects).

William Davis

unread,
Aug 4, 2015, 1:46:36 PM8/4/15
to Google Web Toolkit, wallac...@gmail.com
After more development I have another question regarding this multi project set up so that the compiler can detect changes in the source code when running super dev. Everything works correctly if I declare the sibling projects (library-core in this case) as modules in the parent pom of the web app project. However, I think this is not the best practice. For instance, if I had the library deployed and not checked out locally I would want it to resolve the dependency, this would cause an error with the pom trying to find the sibling project. But if I do have the library checked out locally, my goal is to have a set-up where I don't have to declare sibling projects as modules and the incremental compile works when running super dev (changes in any project's java files are detected and a packaging is not required).

While looking for a solution I found the lifeycle mapping here:

https://github.com/tbroyer/gwt-maven-plugin/blob/master/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml

I notice that on the import-sources goal, the action is ignored. If instead runOnIncremental was set to true wouldn't the resolution of artifacts from the local workspace work with incremental compile? Can you help me understand why you set this to ignore and what is the best way to set up the projects so that changes in the library are detected when running super dev even if the module is not declared in the parent pom of the web app?

Hope that all makes sense.
Thanks,
Will

Thomas Broyer

unread,
Aug 5, 2015, 6:19:44 AM8/5/15
to Google Web Toolkit
This is just how Maven works. A workaround is to create a POM with that declare both projects as submodules and run Maven on it instead: mvn -f workspace.pom gwt:codeserver (this is basically what "resolve dependencies from the workspace" do in Eclipse)
Reply all
Reply to author
Forward
0 new messages