Friday, March 31, 2017

Re: How to deal with transitive maven dependencies?



On Thursday, March 30, 2017 at 6:56:56 PM UTC+2, Magnus wrote:
Hello Thomas,

thank you very much, but I only understand parts of your posts, because maven is still new to me...

Actually, nothing. Nothing on the Maven side though.

Yes, I can validate this by doing mvn gwt:devmode and the app works, nevertheless what eclipse thinks is wrong...
 
The problem is with M2Eclipse, but I don't know it enough to know how you're supposed to work with it and give you any guidance here.

Well, I was used to do everything in eclipse: create gwt project, compile, run, debug, ... I just migrated one general library (pure java and gwt code) and two apps (which I recreated with webAppCreator -templates maven) to maven.
When I make changes to the library, I execute mvn clean compile package install. I feel that some of these goals should be triggered by others, but I call them all to make sure to end up in a defined state.
When I make changes to one of the apps, I execute mvn clean compile package gwt:devmode.

I know that all these goals must be redundant and triggered by each other somehow, but during the migration of my projects I have seen many problems that disappeared when repeating the different maven goals...

See my previous message (in another thread) where I touched those goals.
Hint: remember that Maven lifecycles are linear (they're not a graph), so "install" implies everything before it (includes "compile" and "package"; and "package" implies "compile").
For non-lifecycle goals (such as gwt:devmode), the doc tells you what lifecycle phase it triggers (and the doc is generated from annotations in the code that Maven actually use to determine what it has to do, so it's really documentation about the actual behavior, without a risk of disconnect or being outdated). In the case of gwt:devmode, it triggers "process-classes", which comes just after "compile" in the lifecycle (and as a rule of thumb, you should always use "process-classes" rather than "compile"): https://tbroyer.github.io/gwt-maven-plugin/devmode-mojo.html
 
The problem is that "mvn war:war" is somehow invoked (do you invoke it yourself manually, from within Eclipse? possibly as "mvn package") and it resolves its dependencies from the workspace (by default at least), similar to a reactor build.

To reproduce the problem I don't need to call anything: I simply open the pom.xml in eclipse, remove the "provided" scope, and save the pom.xml file. Then, immediately, the error marker appears.

BTW: I don't know "reactor builds", so I cannot follow your additional words:

See https://maven.apache.org/guides/mini/guide-multiple-modules.html
tl;fr: a "reactor build" is a build in a multi-module project (where one POM has <packaging>pom</packaging> and lists submodules in a <modules> element). The build has to be done on that one POM, not in a subfolder corresponding to a submodule (in which case it's just a normal build).
 
 
But when resolving the library, it won't build/package it! and Maven's default behavior when trying to resolve unpackaged dependencies from a reactor build, is to take target/classes if the dependency has <packaging>jar</packaging>
This can happen in regular reactor builds when you e.g. run "mvn test": it'll run "mvn test" on the first submodule, then "mvn test" on the second submodule, and if the second submodule depends on the first one, then its target/classes is used (because "test" comes before "package" in the lifecycle). This is a design flaw in Maven (if you ask me), and one of the reasons I generally recommend using other builds tools (e.g. Gradle) instead.
If you disable resolution of dependencies from the workspace in Eclipse, then the "mvn war:war" will resolve the library from the local repository instead (which means you'd have to "mvn install" the library to have the app see the changes).

The only thing I understand in this paragraph is that I have to "mvn install" the library, what I am actually doing, so that the apps can see it.

Since my app works when doing everything on the command line, the only thing I want is that the error markers disappear (assuming that they are false positives)...

Then all you should have to do is telling Eclipse to stop resolving dependencies from the workspace (and only from the local repository).
IIRC, right-click on the project,→ Maven → uncheck the menu item talking about resolving from the workspace.
See https://books.sonatype.com/m2eclipse-book/reference/eclipse.html#eclipse-sect-resolving-dependencies (this book is a bit old and no longer maintained)

It seems strange to me though that Eclipse would try to package the project, did you change the preferences of goals Eclipse should run on project import or when updating project configuration?
https://books.sonatype.com/m2eclipse-book/reference/preferences.html#preferences-sect-maven-preferences
 
 
My (personal) recommendation is to work with reactor (multi-module) builds, to only ever execute Maven commands on the root module, and to only ever use the "package" and "verify" lifecycle phases (and possibly "install" and/or "deploy" if you really need them).

I would like to follow this recommendation, but what exactly do I have to do?

Assuming you have a folder "project" containing two subfolders "lib" and "app" containing your library and application projects respectively, then create a pom.xml in "project" with <packaging>pom</packaging> and this snippet:
<modules>
  <module>lib</module>
  <module>app</module>
</modules>
Then run all your Maven commands in the "project" folder (never in the "lib" or "app" subfolders).
For gwt:devmode, you'll want to move the configuration up into this POM (and adapt the various paths and configuration). See my gwt-maven-archetypes for examples of this.
 
This is one reason I built the net.ltgt.gwt.maven:gwt-maven-plugin, because the old org.codehaus.mojo:gwt-maven-plugin could work that way.

This is one big questionmark for me! I am evaluating the different GWT maven plugins for a while, and I learned that yours is the one that is recommended. Then, I found that webAppCreator -templates maven creates a project template that I can work with. And I noticed net.ltgt.gwt.maven in the pom.xml. Therefore, I thought that I am using your plugin. But the error message discussed here is a "MojoExecutionException". The word "Mojo" seems to refer to the other plugin. That's confusing to me. Can you resolve this?

"Mojo" is a Maven term, it stands for "Maven plain Old Java Object": https://maven.apache.org/plugin-developers/
It's a bit unfortunate that the "community" of plugins was named "Mojo" (formerly CodeHaus Mojo, now MojoHaus) but there's nothing I can do.

--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscribe@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.
Visit this group at https://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment