Skip to content

Conversation

@desruisseaux
Copy link
Contributor

Maven 4 automatically generates a consumer POM after a successful build. This consumer POM already excludes some elements from the original POM such as the list of sub-projects. However, when building a modular project (in Java sense), there are two more elements that need to be excluded:

  • <build> because it contains (in the modular case) the <sources> element which is not compatible with the Maven 4.0.0 model. This pull request removes the full <build> element instead of only the <sources> child element because the build configuration is invalid without the sources, and I think that information about how the project was built is not really necessary for consumers anyway.
  • <dependencies> because the effective dependencies will be dispatched in the POM files generated by maven-jar-plugin for each Java module from the content of module-info.class.

@desruisseaux desruisseaux requested a review from gnodet January 11, 2026 18:21
Copy link
Contributor

@elharo elharo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

build yes
dependencies maybe. I'm not sure.

@desruisseaux
Copy link
Contributor Author

Just in case there is an ambiguity, <dependencyManagement> is untouched. Only <dependencies> is removed, and only for module source hierarchy. Classical projects (package hierarchy) stay as before, even if the project contains a module-info file.

In the case of multi-module projects, there is a choice:

  1. The POM of each Java module can be a copy of the project pom.xml with dependencies filtered for keeping only the dependency actually used in module-info.
  2. The POM of each Java module can declare the project pom.xml as its parent, then declare the dependencies actually used in module-info.

In approach 1, the content of the project pom.xml does not matter much as that POM is totally ignored after the build (but preventing its deployment on a repository would be useful, as it would be noise). This pull request could be ignored.

However, approach 1 leads to a lot of duplication in the POM of each Java module. For that reason, I'm now more inclined to approach 2. It also appears to be simpler, because it removes the need to duplicate the work of Maven core into the JAR plugin (because we can inherit the effective POM generated by Maven core). However, approach 2 can work only if we remove <dependencies> from the parent pom.xml for making possible to declare smaller set of dependencies in the child POM of each Java module.

@rmannibucau
Copy link
Contributor

build was originally removed then was reverted since the info has value, how do we plan to keep the information in consumer pom - or rephrased, how do we plan to expose it in a ~stable model? Also the "comes from parent" info should be somewhere to understand why a module get a totally unrelated dependency on consumer land and have more serennity excluding it IMHO - not that rare actually for provided scope for ex.

@desruisseaux
Copy link
Contributor Author

build was originally removed then was reverted since the info has value, how do we plan to keep the information

It would be easier to answer this question with a use case. Why a user would need build information? Removing the <sources> element for compatibility with model 4.0.0 makes the <build> incomplete anyway. Which information are considered important?

Also the "comes from parent" info should be somewhere to understand why a module get a totally unrelated dependency on consumer land

I do not understand well. The consumer POM get a subset of the dependencies of the project. Which unrelated dependencies are we talking about?

@rmannibucau
Copy link
Contributor

@desruisseaux while we say consumer pom == runtime dependency set we are good, it means we prune optional, provided, test dependencies too. But it also means we prune all other kind of dependencies (javadoc, annotation-processor etc... and extension ones - will start to be complicated, think bundle for OSGi for ex). So basically we keep dependencies almost as this with just the flatten option.

The dependency part I'm thinking about is parent gets my-java-util-logging-log-manager, so all children get it even the lib/ module which doesn't care. Loosing the inheritance info makes it harder to understand without checking original sources and automotion is harder if you need an unstable metadata source (build pom).

This is part of the pom metadata which are consumed, now it is also common to put metadata in the pom elsewhere, properties are one location, plugins are another one.
I can totally hear, "no this is wrong", but then we need a location which would be passthrough to consumer pom to let it be used downstream before downloading an artifact.

All that to say that I think we should be able to keep the original info somehow in a normalized way.
Fine if it needs to enhance the model to get there but just dropping will recreate the issues we original had.

@desruisseaux
Copy link
Contributor Author

Optional, provided and tests dependencies are not in <build>, so those ones are not impacted by the removal of <build>.

Javadoc and annotation dependencies are no longer in <build> with the new model. They are ordinary dependencies with a specific <type>. Therefore, they would not be impacted by the removal of <build> neither. For compatibility with codes that were used to search for this information in plugin configuration, the <build> is not removed in classical Maven projects.

The dependency part I'm thinking about is parent gets my-java-util-logging-log-manager, so all children get it even the lib/ module which doesn't care.

But this information is not in <build> neither, so it would be a separated discussion not impacted by the removal of <build>.

@rmannibucau
Copy link
Contributor

Optional, provided and tests dependencies are not in , so those ones are not impacted by the removal of .

the point is more that we can't drop useful information cause it is not used for a single use case without a proper replacement, think OSGi requirement (~provided scope for ex).

Javadoc and annotation dependencies are no longer in with the new model. They are ordinary dependencies with a specific . Therefore, they would not be impacted by the removal of neither.

Yes but to complete your PR idea you must remove them from <dependencies> too cause the consumer pom doesn't need them at all and more generally any dependency which is not a jar/zip of runtime scope should be removed - war overlay case included.

But this information is not in neither, so it would be a separated discussion not impacted by the removal of .

Well my point was that removing build is an issue we hit so we can't do it now more than before since we dont have a fix for it plus the fact ultimately cleaning up dependencies will be challenging too with the new type workaround.

@desruisseaux
Copy link
Contributor Author

the point is more that we can't drop useful information cause it is not used

This is not a general rule. The encapsulation principle in object oriented programming recommends the opposite: do not expose implementation details unless you have to ("in case of doubt, leave it out"). I'm in favour of this approach. We have the opportunity to remove <build> in multi-module projects because they are a new feature. Keeping <build> now is an unnecessary risk, as it does not provide the information required by the use cases in the previous comment anyway — it is much safer to leave <build> out and add more information later as we get better understanding of what piece of information is really needed.

Yes but to complete your PR idea you must remove them from too cause the consumer pom doesn't need them

This is not the topic of this pull request. This pull request removes all dependencies in the parent consumer POM, and the JAR plugin as proposed reinjects only the dependencies that are declared in module-info.class of each module. Addressing above comment would be the topic of a separated issue in maven-jar-plugin.

Well my point was that removing build is an issue

See above: keeping the build is an issue, because it ties us forever for nothing (the dependencies information are not in <build>). If an information appears to be really missing, it is much safer to revisit the situation when we have the use case.

@rmannibucau
Copy link
Contributor

This is not a general rule. The encapsulation principle in object oriented programming recommends the opposite: do not expose implementation details unless you have to ("in case of doubt, leave it out").

well what is your proposal for people using it, pom.xml is our descriptor, it is a good location to expose data.
agree encapsulation is not bad - even if unrelated to OOP there - but we dont have this expose principle, exactly the one I request before we drop things.

Keeping now is an unnecessary risk

once again, we did drop it and had to revert it so it is not a risk but a bug.

This is not the topic of this pull request.

it is totally, the topic is "what do we want to keep in consumer pom", there is no real point starting to drop random data without cleaning it all IMHO, just mean we'll have multiple breaking phases

Addressing above comment would be the topic of a separated issue in maven-jar-plugin.

Think it is just your niche/JPMS case but far to be mainstream today so will not cover much sadly, so not a global solution.

See above: keeping the build is an issue, because it ties us forever for nothing

I ack that but we need a solution before dropping it, so I'm -1 for this PR until we propose something.

@desruisseaux
Copy link
Contributor Author

once again, we did drop it and had to revert it so it is not a risk but a bug.

The reasons why it was reverted are not necessarily valid anymore. If the reason was Javadoc and annotation dependencies, it was a valid reason in Maven 3 but is not valid anymore with the new model since those dependencies are no longer in the <build> element.

it is totally, the topic is "what do we want to keep in consumer pom"

There are two separated discussions: <build> and <dependencies>. For the latter, the answer is no dependency at all in the parent POM of a multi-modules project. For this pull request, that's all. For a discussion about the selection of dependencies in child POM, this is a topic for the proposed maven-jar-plugin 4.x, not for this pull request.

Think it is just your niche/JPMS case but far to be mainstream today so will not cover much sadly, so not a global solution.

I know that you dislike JPMS. But this pull request has no impact on non-JPMS users. Keeping <build> for JPMS users is an unnecessary risk. Risky because <build> amputated from its <sources> is misleading, and it is much more difficult to fix something wrong in the future than filling a hole. Unnecessary because above discussion did not gave a single example of an information located in <build>, only a vague "we had to revert" in a context that is probably not valid anymore.

Again, please keep in mind that this pull request applies only to projects that use Module Source Hierarchy. If you do not like JPMS, you are not impacted.

@rmannibucau
Copy link
Contributor

Again, please keep in mind that this pull request applies only to projects that use Module Source Hierarchy. If you do not like JPMS, you are not impacted.

I'll be fine but our ecosystem will be inconsistent, do we want that? 🤔

@desruisseaux
Copy link
Contributor Author

I'll be fine but our ecosystem will be inconsistent, do we want that?

Fully embracing Java modules requires a lot of changes in developer's habit. I don't see any way to avoid inconsistency in the way to declare dependencies (Javadoc and annotation moved from plugin configuration to ordinary dependencies), to declare sources (plugin configuration and <sourceDirectory> replaced by <sources>), to organize modules (Module Source Hierarchy), etc. This pull request is a small change in comparison.

@rmannibucau
Copy link
Contributor

I don't see any way to avoid inconsistency in the way to declare dependencies

hmm, this is not the point, the point is that I'd like to avoid a consumer pom to be different if the upstream project is JPMS or not, there is no reason we make it different.

@desruisseaux
Copy link
Contributor Author

hmm, this is not the point, the point is that I'd like to avoid a consumer pom to be different if the upstream project is JPMS or not, there is no reason we make it different.

A consumer POM of a classical Maven project can be a valid 4.0.0 model. But in a multi-module projects, the <build> element cannot be a valid 4.0.0 model. We must at least remove the <sources> element, which change the semantic.

In other words, in a non-modular project, it is possible to produce a consumer POM in such a way that the users can trust the <build> as an accurate description of how the model was built. In a multi-module project, this is not possible.

@rmannibucau
Copy link
Contributor

@desruisseaux I understood, we still need a way to solve it globally to not have a solution for JPMS, another one for another new feature (subprojects breaking renaming for ex) etc..

One option was to say we do use build pom but we don't have a pivot format yet so no solution so I think this PR must await we have a global solution solving the root issue and enabling user to use the new stable model for future dev - and ack we break for maven 4 once for all.

Just my 2 cts

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

Successfully merging this pull request may close these issues.

3 participants