scijava/jgo

cant handle managed dependencies

warmuuh opened this issue · 8 comments

It lookes like it ignores managed dependency entries in parent poms.
common usecase is spring/spring boot applications, it then picks the wrong versions and application does not start.

example:
parent => org.springframework.boot:spring-boot-starter-parent:2.0.0.M1
which includes managed dependency for e.g. jackson-core:2.9.0.pre3 but jrun picks 2.6.1

@warmuuh Thanks for the report. Can you give a sample invocation of jrun which does the wrong thing?

no, sorry, as i did not upload the project to any public repository.
if i find time, i can create a sample project, but i suspect that this happens, because mvn dependency:resolve returns different dependencies for the project-pom VS the jrun-generated one. why not just use the pom in the jar itself? (META-INF/maven/...)

i suspect that this happens, because mvn dependency:resolve returns different dependencies for the project-pom VS the jrun-generated one.

Certainly possible, though it would surprise me. The dependency versions which were used to build the requested project should match the ones desired by that artifact at runtime according to Maven, including versions gleaned by dependency management.

If you find time to create an MCVE, I would greatly appreciate it!

why not just use the pom in the jar itself? (META-INF/maven/...)

There are several reasons:

  • A new POM must be synthesized when you add additional classpath elements via the + syntax, since the additional elements are not part of the original POM.
  • Using the original POM would inflict its optional dependencies—this may be desired, but it may not be.
  • Using the original POM would not allow to override which remote repositories are used via the <repositories> section.
  • The artifact in question might not have been built with Maven, and therefore might not have a POM in the META-INF/maven folder.
  • Most crucially: the project's embedded POM was designed for the use case of building that very project—not for the purpose jrun needs. The project POM is free to do whatever it wants at any phase of the Maven build—for example, it might perform inappropriate operations even when goals like dependency:resolve are invoked directly. It is much, much safer to create a simple POM which declares a dependency on the project(s) in question, and resolve the dependencies from that.

i setup an example demonstrating this issue here:
https://github.com/warmuuh/jrun-managed-dependencies
all details are in the readme. hope that helps

Thanks @warmuuh, that is helpful!

Indeed, the transitive dependency versions do not match, due to nuances of Maven's support for managed dependencies.

I have created a gist which succinctly illustrates the problem, as well as a workaround I found. I also posted a question on StackOverflow about it, since the need for this workaround seems extreme to me.

I implemented the workaround (c17b8f5) as a new -m flag which you can pass to jrun. Please try it with your projects and let me know how it works!

An aside about uber-JARs

Note that Spring Boot, by default, creates executable fat JARs which are not intended to be reused from other projects as dependencies (see this SO thread for details). Since jrun works by reusing the requested project as a dependency, this could be problematic for you (though I don't know Spring Boot well, so cannot really comment more concretely how/why). You can avoid potential problems by adding the following to your project POM's spring-boot-maven-plugin declaration:

  <executions>
    <execution>
      <goals>
        <goal>repackage</goal>
      </goals>
      <configuration>
        <classifier>exec</classifier>
      </configuration>
    </execution>
  </executions>

In theory, this lets your project be reused as a normal dependency now, although it will still suffer from the aforementioned dependency version skew due to how Maven's dependency management feature currently works, unless you pass the new -m flag.

'-m' works fine, thanks for implementing it, really useful.
I wouldn't want to change the project pom, but the added option is just fine

This issue has been mentioned on Image.sc Forum. There might be relevant details there:

https://forum.image.sc/t/a-backwards-compatible-way-to-drive-imagej-update-sites-with-maven-artifacts/59620/1

This issue has been mentioned on Image.sc Forum. There might be relevant details there:

https://forum.image.sc/t/jgo-dependency-tree-inconsistent-with-in-project-dependency-tree/79347/3