Issue Details (XML | Word | Printable)

Key: MNG-624
Type: Improvement Improvement
Status: In Progress In Progress
Priority: Blocker Blocker
Assignee: Ralph Goers
Reporter: Brett Porter
Votes: 105
Watchers: 67
Operations

If you were logged in you would be able to see more operations.
Maven 2

automatic parent versioning

Created: 20/Jul/05 08:56 PM   Updated: 04/Nov/08 08:48 AM
Component/s: Inheritance and Interpolation
Affects Version/s: None
Fix Version/s: 3.0

Time Tracking:
Original Estimate: 4 hours
Original Estimate - 4 hours
Remaining Estimate: 4 hours
Remaining Estimate - 4 hours
Time Spent: Not Specified
Remaining Estimate - 4 hours

File Attachments: 1. Text File MNG-624-maven-2.0.x-r507648.patch (41 kB)
2. GZip Archive MNG-624-tests.tar.gz (7 kB)

Issue Links:
Duplicate
 
Related


 Description  « Hide
(this may be bumped to 2.1 or even made WON't FIX as it is contentious - see MNG-521)

currently, you have to specify the parent version when extending which makes a project stand alone very easily, but has the drawback of being a maintainance problem when you start development on a new version. Tools can help, but it would be nice not to have to rely on them.

One alternative is to allow the parent version to be omitted, and when it is it is assumed you want the latest. The parent is used from the reactor or the universal source directory. IT may also be read from a LATEST in the repository though this is contentious - it may be better to simply fail in that environment and require builds be in a known checkout structure for building individual projects.

This also introduces the need for tool support to populate the version on release and deployment for reproducibility.



 All   Comments   Work Log   Change History      Sort Order: Ascending order - Click to sort in descending order
Jeff Jensen added a comment - 06/Nov/05 11:30 AM
On a different use case, with my current understanding, this seems to easily make sense when specifying <relativePath>. In fact, in that case, it seems one could leave off all three: <groupId>, <artifactId>, <version>, since it simply uses the specified one.

Brett Porter added a comment - 06/Nov/05 07:56 PM
tha'ts not the meaning of <realtivePath> - it still relies on the correct data being used so that the project can be built in isolation. Relative path is a hint for the universal source directory.

Brian Fox added a comment - 11/Jan/06 07:40 AM
here's my 2 cents: What if the parent version could take a tag like LATEST and then the release plugin could resolve it like it does with SNAPSHOTS. IMO, if you can't define your parent in a flexible way, it almost make it pointless to be able to inherit the version from the parent....you still need to go to each pom and update the parent rev. The problem with it always taking the latest is when you tag something, if you go back later the parent could be different.

Arik Kfir added a comment - 29/Apr/06 10:24 PM
two more cents: imo the algoritm should do the following: (in specified order)

1. if a version is given, resolve it from reactor/repository
2. otherwise, if a path is given, use that
3. otherwise, if the project has an SCM, retrieve it from the scm (using same tag/branch/etc)
4. error


Kevin Sheehan added a comment - 11/May/06 12:17 PM
...and another two cents...

It appears (from my tests) that the <parent></parent> element is absolutely the first tag accted upon when encountered in the POM. That makes sense HOWEVER... I would like to read / load / substitute variables in that section.

i.e.
mvn -Dapp.version=1.0-SNAPSHOT compile

with POM that contains
...
<parent>
<artifactId>artifact-id</artifactId>
<groupId>group-id</groupId>
<version>${app.version}</version>
</parent>
...

should be the same as
...
<parent>
<artifactId>artifact-id</artifactId>
<groupId>group-id</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
...

but is not as the <version>${app.version}</version> is LITERALLY substituted rather than recognizing this as an instance of variable substitution.

Allowing variable substitution in the <parent></parent> section should provide enough flexibility to successfully close this.


Prasad Kashyap added a comment - 08/Jun/06 02:10 PM
The Geronimo project has about 145 pom.xmls layered in 3 to 4 tiers.

Ideally, we would like to set the version in one single place and use it repeatedly everywhere. This would include the version for the <project> and for the <parent>. Example :

<project>
<parent>
<groupId>org.apache.geronimo</groupId>
<artifactId>geronimo-parent</artifactId>
<version>${geronimoVersion}</version>
</parent>

<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.geronimo.applications</groupId>
<artifactId>applications-parent</artifactId>
<version>${geronimoVersion}</version>
...........

Such a thing is not possible.

If we want to do a top level build with 1 single 'mvn' command, then we cannot use ${geronimoVersion} while declaring the project's and
parent's version. We will have to explicitly define the version. That would mean changing every single pom.xml every time the release
changes.

Setting the version in -D doesn't work either.


Brett Porter added a comment - 08/Jun/06 06:42 PM
you never need a ${geronimoVersion} property. version is inherited. And you'll have to specify the parent version until this new feature is implemented (you can't get the version of the parent to use from the parent

You can use the release plugin to automatically update these for you in the mean time.


Christian Goetze added a comment - 11/Jan/07 01:41 PM
I would like to add my support for allowing the use of ${...} in the <parent>...</parent> sections. I just fail to see any downside to it, and it would certainly make my life easier, as I cannot use the release plugin as it is...

Eric Brown added a comment - 22/Feb/07 04:39 AM
The attached patch and 16 integration tests fixes this issue by allowing the following:
  • Variable expansion works in the <parent> section of pom-s for version, groupId and artifactId
  • The same elements are all optional. At the extreme, this means most times <parent/> will work.

There is a rule for this to work, however. You must have enough of your development tree on disk that maven can walk the directories (<relativePath> still works) to resolve variables and/or find inferred elements that are missing.

Implementation Notes:

  • All existing and 16 new integration tests are passing. The code-path and what's going on really doesn't change for existing projects that have explicit <parent> sections.
  • It passes my complex 202-module project.
  • Most of what is going on is that maven now guesses and does re-interpolation later to verify (and/or) continue its inferencing. I call it "expansion" in a few places because it is more than just interpolation, profiles also have to be expanded - but the code was all there, I just refactored slightly.
  • When pom-s are installed and deployed, if any part of their <parent> specification was inferred or re-expanded, it is no longer possible to simply copy the source pom.xml unmodified to the local and/or remote repository. Doing so would make it impossible to build from somewhere other than "trunk" as when building from the middle of a tree, artifacts that are elsewhere in sibling or cousin nodes of the tree are actually fetched from the repository and their parents in-turn from the repository as well. But the parents couldn't be found in the repository because the parent section was missing! So maven now detects that the parent section was missing or needed expansion due to the presence of variables and makes sure the parent section is present before writing a pom to a repository. I'm not fantastically pleased with this implementation for a couple reasons: (though it works and my vote would be to accept it as is - I doubt it is the worst ugliness in the code)
    • The pom in the repository looses all comments and formatting from the original.
    • The way I hooked it into the artifact and suck it back out again when installing and deploying pom-s just felt hackish. Though I really don't see any other way to pass the needed information around as this information obviously was not intended to be passed between the maven-project and maven-artifact modules in the architecture.

BTW, The reason I spent so much time on this is because I have 202 modules and release twice / month. My svn logs are littered with crap from changing version information in my 202 pom-s and I find it very annoying. Maven is a great tool, but I've never worked with or built a build system where I had to keep version information in so many places. I know there are tools to manage it, but it is still uglier than the patch I've submitted here IMO. YMMV


Jason van Zyl added a comment - 22/Feb/07 04:00 PM
I will take a look but have you run all the integration tests and are certain it doesn't whack anything else. If so then I think we could consider it. I would patch trunk and backport it.

Eric Brown added a comment - 22/Feb/07 04:50 PM
Yes, all the integration tests run. Both the ones still attached to the maven-2.0.x branch and the ones in core-integration-tests.

trunk wasn't working for me at the time I started this, so I did it against 2.0.x. I should have dug a bit further I suppose. If you want to open a new issue for this for 2.1, I can look at it when I get a chance, but it'd be great to get this in 2.0.6.


Brett Porter added a comment - 22/Feb/07 05:38 PM
I'm certainly interested in taking a look at this. Hoever, I'm not sure if major functionality should be introduced in the .0.x line - esp. if a 2.1 alpha is not far behind.

Jason van Zyl added a comment - 31/May/07 10:24 PM
Unmarking patch, I will take it.

Jason van Zyl added a comment - 04/Jun/07 06:57 PM
This will not make it into the first alpha without some discussion.

Brett Porter added a comment - 05/Sep/07 02:08 AM
lots of votes - Jason, did you have something in mind for this already based on your last comments?

Ian added a comment - 23/Nov/07 12:30 PM
Allowing variable substitution in the parent section would fix MNG-3070 as well. I've encountered the same problem as Prasad Kashyap with labelling builds on the fly. This also has a side effect that if you have a hierarchical directory structure you can't guarantee to be able to build from an arbitrary sub directory. I think that what is happening is like this - imagine parent project A with sub project B which is dependent on C which is also a child of A.:

/projectA
/projectB child of projectA dependent on projectC
/projectC child of projectA

If you build from directory B it resolves C as a binary artifact, looks the parent pom of C up in the repository, fails to make the variable substitution and then explodes. This makes it impossible to label builds on the fly AND build from any directory without editing all your pom.xml files.


Michael McCallum added a comment - 16/Jan/08 05:43 AM
Can we please default to forcing a parent version for build reproducibility and just allow variable substitution for people that really really want complicated builds?

A small but i think very pertinant rant...

I really feel like the problem is with the way people are setting up there projects and thinking about their pom hierarchies. Pom hierachies should should be functional rather than packaging, where as modules are packaging and not functional.

Consider it like a java project do you inherit all the way down a package hierarchy?? no because it makes not sense you inherit or implement from super types that give you the specific functionality that you need. e.g. assembly parents, webapp parents, jaxb parents.

You then group your classes together in packages as they form a component... similar concept with modules projects... they really only need to build similar

Dependencies should very rarely be in parents if at all you should use standard OO principles to encasulate them in composites that are reused by muliple projects as dependencies.

I would take a very different approach and completely disallow modules projects from being parents and vice versa.

We have over 145 artifacts and we release once a week... we don't have dependency changes littered all over the subversion logs... we use ranges and effective versioning processes to keep a consistent build hierarchy... its been a painful road thats really coming together with 2.0.8.

my 2c


Ian added a comment - 28/Jan/08 01:53 PM
Having done all of that, I still think it would be good to be able to dynamically label all the build artifacts with the same version, including the top-level pom.

Jean-Charles Meyrignac added a comment - 15/Feb/08 04:26 AM
I was building Selenium, and found that I could propagate automatically the version number as follows:
<parent>
<groupId>org.openqa.selenium</groupId>
<version>${SeleniumVersion}</version>
<artifactId>selenium-rc</artifactId>
</parent>

This worked on Maven 2.0.4, but doesn't with 2.0.6.
Alas, I was forced to upgrade due to maven-assembly-plugin, version 2.2-beta-2-SNAPSHOT, which forces the use of 2.0.6.


Jörg Hohwiller added a comment - 12/Jun/08 03:56 PM
Same idea was suggested in MNG-3267

Henrik Brautaset Aronsen added a comment - 06/Aug/08 06:05 AM - edited
MNG-3057 also has a small patch on maven-install-plugin that fixes the property substitution in <parent>. There's a test case for it in MNG-2446.

Henrik Brautaset Aronsen added a comment - 19/Aug/08 02:12 AM
MINSTALL-50 also has a patch for this issue.

Harsha Rai added a comment - 19/Aug/08 07:07 PM
Hello:

I filed the following:
http://jira.codehaus.org/browse/MARTIFACT-32

The issue is almost the same. I didn't know which maven component the issue belonged to? Is there a workaround for this?

thanks..


Henrik Brautaset Aronsen added a comment - 20/Aug/08 01:46 AM
Harsha: There is a simple patch in MNG-3057 which solves this issue.

Harsha Rai added a comment - 22/Aug/08 10:11 AM - edited
Hello:
Could someone provide a pointer to the process where one can patch and get a release of maven install plugin and manve-project.

I've a simple patch to the problem mentioned in this issue (MNG-624) and MNG-3057.

Also, what is the timeline for the fix proposed here (by Ralph Goers) is getting into the next release of maven.

Greatly appreciate your comments and direction in this regard.

Thanks..
Harsha


Ralph Goers added a comment - 28/Aug/08 03:10 AM
I've committed a fix for MNG-624 onto branch maven-2.1.x-MNG-624 so you all can test it. Here's what I've done:

I'm only trying to resolve the parent version. I could try to resolve the parent groupId and artifactId but I just couldn't think of a reason why they wouldn't be specified.

The version is obtained by
1. Resolving any variables provided via system properties (variables from parents won't be found since the parent isn't known.
2. Looking in the file cache for the resolved parent project using the relative location as the key.
3. Looking for the parent at the relative path on disk.
a. The target directory at the relative path is inspected for a modified pom.
b. The project at the relative path is used.
If at the end of this a resolved parent version is not located throw an Exception. Do not try to recurse to further parents.

You'll notice the comment about looking for the modified pom in the target directory. As part of this fix the parent version, and the project's artifactId, groupId and version are all interpolated. If any of those fields were missing or had variables in them in the original pom then the pom is modified and written to the target directory. Thus, any pom that is installed or deployed will always have these fields resolved.

In looking through the plugins it looked to me that the Eclipse and Invoker plugins are trying to locate the base directory by calling project.getFile().getParentFile(). These will need to be changed to project.getBasedir() since the location of the pom might now be in a different place and project.getFile().getParentFile() might return the target directory instead of the base directory.

Maven 2.1 will require Java 5.

Please test and provide feedback.


Jason van Zyl added a comment - 28/Aug/08 03:38 AM
Ralph, is there some example projects in the branch somewhere? I just want to see what you see as the layout.

I see it as a set of projects on disk, that are all connected, chaining upward to the parent where it has the implicit Super POM parent, or is not connected to its parent on disk. If this is the case then the version element in parent references wouldn't even be required as all the projects are connected. Once you have that contained set then the one version is either specified explicitly or as a property. I always assumed in this case it's all or nothing in that people wouldn't be checking out leaf node projects and trying to build them.


Harsha Rai added a comment - 28/Aug/08 09:15 AM
Hi: Ralph

May be I'm missing something on:
quote:
1. Resolving any variables provided via system properties (variables from parents won't be found since the parent isn't known.

So, what I understand is, the variables in the parent are still not getting expanded.?
If so, I would like to make the following suggestion. We don't have to evaluate variable in parent at the time... Today, when I give
a variable in parent, mvn gets stuck at searching for ${parent} in the repo. in the default project builder. Isn't that simple enough to replace the ${parent} with system property , or project.properties. Once a valid value is found in either of these, one can update the project model with right parent info. Isn't it?

I will try 2.1 and let you know.

thanks..


Ralph Goers added a comment - 28/Aug/08 06:16 PM - edited
If you are doing a multiproject build the projects will be cached internally by their full path. As the various projects are built they will find the fully resolved projects in the cache. Then, as the projects are processed their pom.xml files will be modified so that there are no variables for the artifactId, groupId and version and they will be placed into their respective target directories. If you then do a build from a subproject it will find the pom in the parent's target directory. Since the variables have been replaced there is no need to recurse.

What the comment about the variables not being known means is that before looking for the parent an attempt is made to resolve the version. If they variable for the version is defined in the current pom or a system property it will be resolved. Since the parent hasn't been located yet the variable can't be resolved from there. If the version is resolved by doing this no attempt is even made to look for the parent project. If it isn't then the other steps are followed.


Ralph Goers added a comment - 28/Aug/08 06:29 PM - edited

Ralph, is there some example projects in the branch somewhere? I just want to see what you see as the layout.

I haven't checked in the tests yet. I can attach a few sample projects here. Most were somewhat based on some of the tests that are already attached to the issue, although my patch doesn't support an empty parent element.


I see it as a set of projects on disk, that are all connected, chaining upward to the parent where it has the implicit Super POM parent, or is not connected to its parent on disk. If this is the case then the version element in parent references wouldn't even be required as all the projects are connected. Once you have that contained set then the one version is either specified explicitly or as a property. I always assumed in this case it's all or nothing in that people wouldn't be checking out leaf node projects and trying to build them.

The parent element does not require the version element to be specified. If it is specified it can contain a variable. The only real advantage to using a variable is if you check out a subproject in theory you could build that project in isolation by defining the variable with a -D.