Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'dependencies.dependency.version' for xxx is missing #104

Open
tomaskir opened this issue Jul 24, 2019 · 19 comments
Open

'dependencies.dependency.version' for xxx is missing #104

tomaskir opened this issue Jul 24, 2019 · 19 comments

Comments

@tomaskir
Copy link

Hi there.

I am testing out tiles because I need to bring in Spring Boot (which is normally done through a parent pom) into a project that already has a different parent pom.

I can't touch Spring poms to make our parent into their parent.
I can't make the Spring Boot parent into a parent of our parent (that would bring Spring Boot into all our projects).
So I am hoping to achieve this with tiles.

I have successfully wrote and mvn installed all the tiles I need, and I can inject them into the project's pom.

However, when trying to mvn compile, or even mvn effective-pom, it seems the tiles are not properly merged into the pom.

[ERROR] The build could not read 1 project -> [Help 1]
[ERROR]   
[ERROR]   The project xxx:2.0.0-SNAPSHOT (/home/xxx/pom.xml) has 8 errors
[ERROR]     'dependencies.dependency.version' for javax.servlet:javax.servlet-api:jar is missing. @ line 131, column 21
[ERROR]     'dependencies.dependency.version' for org.springframework.security:spring-security-core:jar is missing. @ line 138, column 21
[ERROR]     'dependencies.dependency.version' for org.springframework.boot:spring-boot-starter-data-jpa:jar is missing. @ line 144, column 21
...

All of these are declared as <dependency> in the project's pom, without specifying a version. The version is supposed to come from Spring Boot's <dependencyManagement> section, which is normally brought in from their parent.

I have moved the <dependencyManagement> into a tile, and this tile is properly brought in in the <tiles> section. (I know this is listed as a smell in the tiles documentation, but this is how Spring Boot does things - I don't have much of a choice)

Few questions:

  • any obvious reason why I am not getting the <dependencyManagement> into my pom?
  • I assume tiles runs before the first Maven validate lifecycle phase - is this correct?
  • is there any way to see the pom after it has been "processed" by tiles to inspect how it looks before it gets passed to the Maven validate lifecycle phase?

There doesn't seem to be much documentation how tiles actually integrates into Maven (when in the lifecycle tiles does it's thing, how to inspect the output pom that tiles generates before it goes to Maven etc.)

Any inside is appreciated, thanks!

@tomaskir
Copy link
Author

tomaskir commented Jul 29, 2019

@talios any chance for a comment?

@talios
Copy link
Member

talios commented Jul 30, 2019 via email

@tomaskir
Copy link
Author

I have made an example where you can reproduce the issue:
https://github.com/tomaskir/maven-tile-depmng

You should just be able to clone this and run ./replicate.sh to see the issue.
You can import the pom.xml in the root of the project to your favourite IDE to see how it's strucuted :)

@tomaskir
Copy link
Author

tomaskir commented Jul 30, 2019

Maybe a bit more on what we are trying to achieve:

  • we will have multiple spring-boot-xx-tiles (for 1.5, 2.0, 2.1, etc.)
    (this is because we use different Spring Boot versions in different projects... it's not trivial to migrate a complex project between Spring Boot versions, so some of our big projects are being kept at older Boot versions)

  • when starting a new project, all that needs to be done is to write a new pom that has our parent-pom as the parent, and includes the wanted spring-boot-xx-tile
    (this makes it super easy to start a new project and bring in all the proper company maven configuration into it)

  • example can be seen in the project-using-tiles, basically a 40 line pom can completely configure a very complex project using the composition tiles can provide
    (we want this for assurance of company-wide rules across all projects, etc.)

Our real setup is of course a bit more complicated, but I tried to make the example as simple as I could while still replicating the issue.

@tomaskir
Copy link
Author

tomaskir commented Aug 4, 2019

@talios I apologize for pushing, but any chance for a comment?

@talios
Copy link
Member

talios commented Aug 6, 2019 via email

@tomaskir
Copy link
Author

tomaskir commented Aug 6, 2019

Unfortunately - when we have a <dependency> without a version element, and no <dependencyManagement> (or a declared parent with one) then that fails that validation. Similarly, when we have a <version>${some.version}</version> declared, but no declaration of the property in either the pom, or parent - again - validation failure.

From what I can gather, the validation looks specifically at the parent declared in the pom early on in maven's operation - unfortunately this is where it hurts us.

So this basically means that transforming Spring Boot parent .poms to tiles would not be possible.

One potential resolution to this is to not use a dependency management section, but just dependencies that magically come into your project when you add the tile (not really ideal).

Indeed this is not ideal - we were specifically hoping to NOT modify the Spring parents, other than copy-paste them into tiles. This is so we can easily verify if we have correct contents of the tile (as compared to the original Spring Boot pom).

This would allow developers to correctly work with Spring Boot without even knowing we are using Tiles instead of the Spring Boot parent.

Another potential resolution ... via the .mvn/extensions.xml file ...
Note these extensions are run ONCE per maven instance (which break within IntelliJ etc. as they maintain a long running maven process) so aren't really ideal for use in reactor projects.

This also doesn't sound like a good solution.

This leads to another issue I noticed in your sample project - the client project is getting a tile-plugin definition from a parent pom

We were hoping to declare this in the parent to avoid repetitive code in all .poms, and to enforce Tiles version from the parent. (instead of having to change all poms to update Tiles version)

All in all, it sound like we are hitting limitations of Maven for what we want to do.
(or we are forced to the limitations with how Spring Boot integrates with Maven)

Do you have any idea if we could do something like the sample project I provided in Gradle?

@drekbour
Copy link

This is the single worst issue I've found in using tiles (appreciate it's not bug but an upstream limitation). It completely fails user expectations that <properties> merge and <version>${some.version}</version> works in their pom.

Is there any active plan on solving it (or another issue raised somewhere)?

@rvowles
Copy link
Member

rvowles commented May 19, 2021 via email

@talios
Copy link
Member

talios commented May 19, 2021

As @rvowles says - an example would be useful. I know Spring Boot makes use of BOM style dependency management - and usually that's pulled into a project as a dependency using the import scope.

Properties for versions work, but only if you actually mention the <version>${some.version}</version> in your pom (and if that's in a tile, that tile needs to declare the property as well).

@drekbour
Copy link

@talios FYI, extensions.xml cannot have config but other plugins simply look for a config file in .mvn once they are bootstrapped.
https://github.com/jgitver/jgitver-maven-plugin/blob/fbcc04cc96cb9f06710e14d95522465afff4770c/src/main/java/fr/brouillard/oss/jgitver/cfg/ConfigurationLoader.java#L48

@rvowles It's summarised above by

The initial maven model is built, and validated, before the tiles plugin is executed .... when we have a <dependency> without a version element, and no <dependencyManagement> (or a declared parent with one) then that fails that validation. Similarly, when we have a <version>${some.version}</version> declared, but no declaration of the property in either the pom, or parent - again - validation failure.

Maven BOM users (a prevalent pattern including any modern usages of Spring Boot which really emphasises it) expect that their app should not ever mention a version for something managed via the BOM (unless you have a burning requirement to pin something):

<dependencies>
  <dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
  </dependency>
</dependencies>

These two patterns are incompatible and make it harder to fully embrace tiles for a lot of projects.

Would be nice if this issue were renamed or, better, a new feature created to encapsulate 'Tiles lifecycle plugin' and what it would add to the capabilities.

@rvowles
Copy link
Member

rvowles commented Sep 29, 2021

Spring Boot is not something that anyone should look for any reason at, it is a fractal of bad design choices, from bottom to top! The abuse of dependencyManagement management is always one that has really, really bothered me.

Maven Tiles was always designed as the anti-thesis of this pattern, so its right that it is hard to smuge the two things together, it is focused soley on solving plugin composition, dependency management is easily managed by other patterns (such as composites). Mark and I have always been about trying to find the best way to do things properly, even if Mark tends to take it a bit far :-) Having been working with a Gradle build, which is an atrocious mess, you will find us less enthusiastic about following Springs path to madness sorry 😂

That said, the concept of being able to auto-update plugin versions I think is useful, and its actually something we could potentially bake into the plugin itself or borg from the Versions plugin. Plugins have their own versions and they have dependency libraries you can add to them, so creating a solution where plugins and their respective dependencies can be kept up to date is a desirable feature.

@drekbour
Copy link

fractal of bad design

Superb :) Not heard that one in a while! I would say to ignore the Spring angle except for two lessons: BOM's are ubiquitous and Spring Boot is a jack-of-all-trades. A more UNIX do-one-thing-well philosophy applied to tiles would be "tile stuff and then get out of the way". This derives the goal of not restricting users in what vanilla Maven features can be used alongside or inside a tile and of ability to update tiles using any mojo they choose.

It feels like a .mvn lifecycle extension allowing "early tiling" would make these viable but I see it's a lot of effort for a usage model you don't wholly support! However, IMHO it is "the next step" should tiles want to advance in capability.

@Rohan427
Copy link

Rohan427 commented Feb 6, 2022

I have similar issues with Spring Boot and I'm now re-thinking my use of it.

I have a Java payment processing library (a SOAP API that allows an external web site to provide online credit card payments) that works just fine. It uses an older version of Hibernate (which I'm not a fan of) and Spring Framework 5.x (I like Springs dependency injection). The only reason I'm looking at Spring Boot is because employers (including contracts) want people that have experience with it, so I am working on getting that experience (and NOT liking it). In my 30+ years of experience, I have found Maven especially and Spring Boot to be more trouble than they are worth. Make and Ant always worked just fine and both are very configurable and I've never had to fight with them like I do with Maven (or Gradle).

Anyway, my issue is similar - no dependency version causes NetBeans 12.6 (and NetBeans 8.2) to fail to import a Spring Boot project without a version. Since Spring does not support anything other than Maven and Gradle (not well anyway), "upgrading" my payment API (which uses Ant) to use Spring Boot has taken far more time then it has to upgrade from EclipsLink to HIbernate, then upgrade the version of Hibernate it uses, or even to change from Hibernate to Oracle's ADF ORM.

@lfvjimisola
Copy link

lfvjimisola commented Dec 29, 2022

Another organization that stumbled onto this one as well.

Out of curiousity, I can see that there are new versions released but it seems a they are normally dependency upgrades and bug fixes rather than additional fixes and features. What is the roadmap for Maven Tiles?

Our organization had really high hopes of Maven Tiles but it might not suit all circumstances. If there is an known issue/limitations with BOMs then perhaps it could be mentioned in the README?

@drekbour
Copy link

If there is an known issue/limitations with BOMs then perhaps it could be mentioned in the README?
Amen.

Warning: I have not personally confirmed the below points about it being ok to use nonsense placeholders. If someone does determin this either way then I can update this comment.

Tiles doesn't (cleanly) support

  • <dependencyManagement> (including BOMs)
    • All managed-dependencies must detect a version, even if it's nonsense or archaic, before tiles are injected
  • <properties>
    • All properties must exist before the tiles are injected.

Placeholders are required to not be missing during earliest POM initialisation which is more about syntactical correctness, they will be replaced with values from your tiles before becoming active. These placeholders must be set in a parent project (since tiles will, by design, never override anything in the local project).

Warning: These workarounds provide the ability to significantly bypass the reproducible-builds property expected by most users/organisations. Tiles imported with open-ended version ranges ([1.0,2.0)) mean the same commit could produce totally different dependencies when executed after a tile is updated.

@rvowles
Copy link
Member

rvowles commented Dec 30, 2022

Open ended dependencies of any kind provide that, but tiles are not intended to be used with dependencies, only for plugins. Composites are used for dependencies, my open source project FeatureHub uses both halves, if that's of use. But we also use trunk based development, differential builds and a monorepo.

@talios
Copy link
Member

talios commented Dec 31, 2022

I did start looking into this earlier today, but ended up going to pub.

However - as @rvowles says tiles is primarily about behaviour - via plugins.

Looking at the maven-tile-depmng mentioned above, your right - that doesn't work. Given the <dependencyManagement> declared is in a parent, it should work, if that parently chain was there prior to the validation step - which I believe occurs earlier than the extensions kick in.

So stubbing the out may work. An alternative, which I'm going to look at tomorrow, is to move the <dependencyManagement> block from the tile.xml to the pom.xml - then add a import <dependency/> block into the child.

My hope then, is that this provides a "best of both worlds" approach - tiling in the behavior, and importing the dependency.

Unfortunately - this doesn't quie work (so I just found out):

[WARNING] 'dependencyManagement.dependencies.dependency.type' for com.github.tomaskir:spring-boot-1.5-tile:xml must be 'pom' to import the managed dependencies. @ line 24, column 23

That project is.... quite a mess tho, esp when trying to tease things apart and see what is actually failing.

The top level pom declares the parent, but also includes the parent (which I believe does get resolved, just confusing), and the moment you don't include that parent anywhere - nothing works due to the lack of groupId's being repeated (again, thats allowed due to the parent). However, the intended use of tiles is to not use parents (if possible).

I noticed when trying to build, nothing seemed to be triggering the build of the parent.

Two options come to mind:

  • Manually add an additional pom.pom file (name just a placeholder) declaring a BOM pom, and add that as an pom artifact, which could then be imported. No change needed to the tiles plugin.
  • Update the tiles plugin with support for attaching a BOM pom (or writing one out from a <dependencyManagement> section of the main pom ( less than ideal, and blurs further the acceptance of dependencies in tiles ).

I think the first option maybe the best option, maintaining the versions is still left up to the tile author by whatever means they see fit (aka not part of the tiles-maven-plugin itself).

@lfvjimisola
Copy link

@talios Thanks for comment. Our team just decided that we won't use Maven Tiles as of now. We are afraid that we end up with other stuff that won't work for us (such as integration with VS Code).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants