what is project.build.directory in ANT - maven

In my project the maven-antrun-plugin is used and in a number of places a property named
project.build.directory
is referenced but i can't understand to what value this property is set. I tried to google and found couple of places where this was mentioned but could not find a formal note on, to what value this property is set.
Also, since I am using the maven-antrun-plugin, it would be nice if you tell me this property is set by Maven or Ant.

project.build.directory is a maven property available as is when your ant script is embedded in your pom.xml
If you call an external ant build file, this property will be available under maven.project.build.directory
By default the value of this property is the target directory.
This default value can be changed by adding a <directory> element in the <build> section of your pom.xml:
<build>
<directory>something</directory>
...
</build>
More about maven properties in maven-antrun-plugin here
Specific quotes from this source:
All of the properties available to maven are also available in the target configuration. However, you may want to call an external Ant build script using the ant task. To avoid name conflicts, only a subset of the properties are passed to the external Ant build. These include all properties defined in the properties section of the POM. It also includes prefixed versions of some of the commonly used Maven properties.

Related

Maven: Define SuperPOM property project.build.directory over command line

I am building my maven project with GitLab CI on a docker file.
I would like to configure my pipeline with a "compile" stage and a "test" stage. To be able to do that, I need to set the property project.build.directory, which is defined in the maven super POM, to the docker cache so the compiled artefact does not get lost between the jobs.
project.build.directory is a predefined maven property. Therefore I would think that I am able define it with the CL parameter -Dproject.build.directory=anotherDir. This somehow does not work and my project still gets built to the default directory target.
If I modify my POM with
<properties>
<buildDir>target</buildDir>
</properties>
<build>
<directory>${buildDir}</directory>
</build>
and call mvn clean install -DbuildDir=customTargetDir, my project gets built to the customTargetDir as expected.
Why is that? I really don't see a difference. I both cases, I define the value of an existing property.

Execute Maven plugin with custom classpath entry

I would like to call a maven plugin with a custom entry on its classpath. This is usually possible by adding <dependencies> inside the <plugin> tag. The problem is, what I would like to add to the classpath is not a maven artifact, but some random folder in my project (the reasons for this are quite obscure, I need a resource file to be present of the classpath, but I must not copy it to the /target/classes due to IDE shenanigans).
Is there any way to specify truly arbitrary classpath entries for a maven plugin?

how to know the value variable defined in pom.xml?

I have some multi-module Maven project, I am looking through whole pom.xml. I am beginner for Maven project, so not have enough knowledge to understand it comprehensively. There is some variable defined in pom.xml,
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>xxx</artifactId>
<version>${project.version}</version>
</dependency>
I searched whole properties defined in pom.xml cause those are that I know of which variable can be defined for pom.xml.
Does anybody know about how I can figure I what the 'project.groupId' is? Is there any files or environments I can search for?
I searched whole properties defined in pom.xml cause those are that I know of which variable can be defined for pom.xml. Does anybody know about how I can figure I what the 'project.groupId' is? Is there any files or environments I can search for?
If you would like to explore the various properties, you may find the output of mvn help:expressions instructive; it lists the various starting points of such property expressions, e.g., ${project} (the current project’s POM) or ${settings} (the user’s settings).
You can then use mvn help:evaluate to explore the values of these properties. For example, if you enter ${project} on evaluate’s prompt, you will see an XML rendition of the ${project} object. Within this XML element, you can select child elements by a dot-separated path. A property like ${project.build.finalName} will evaluate to to the value of the <project> > <build> > <finalName> element.
you can refer those links for multi-module Maven POM.xml configuration.
http://www.codetab.org/apache-maven-tutorial/maven-multi-module-project/
http://www.avajava.com/tutorials/lessons/how-do-i-create-a-multi-module-project-in-eclipse.html

How can I update a property in a Maven POM?

I have two top-level Maven projects, backend and frontend, that advance versions at their own individual pace. Since each has multiple modules, I define my dependency versions in dependencyManagement sections in the parent/aggregate POMs and use a property for the version number.
I want to cleanly update the property with the version number on frontend, preferably arbitrarily, but I can live with requiring a live upstream version to match. I've tried using versions:update-property, but that goal seems to be completely non-functional; regardless of whether there's actually a matching upstream version, I get this debug output:
$ mvn versions:update-property -Dproperty=frontend.version -DnewVersion=0.13.2 -DautoLinkItems=false -X
...
[DEBUG] Searching for properties associated with builders
[DEBUG] Property ${frontend.version}
[DEBUG] Property ${frontend.version}: Looks like this property is not associated with any dependency...
[DEBUG] Property ${frontend.version}: Set of valid available versions is [0.9.0, 0.9.1, 0.9.2, 0.9.3, 0.9.4, 0.9.5, 0.10.0, 0.10.1, 0.11.0, 0.12.0, 0.13.0, 0.13.1, 0.13.2, 0.13.3]
[DEBUG] Property ${frontend.version}: Restricting results to 0.13.2
[DEBUG] Property ${frontend.version}: Current winner is: null
[DEBUG] Property ${frontend.version}: Searching reactor for a valid version...
[DEBUG] Property ${frontend.version}: Set of valid available versions from the reactor is []
[INFO] Property ${frontend.version}: Leaving unchanged as 0.13.1
[INFO] ------------------------------------------------------------------------
I've specified -DautoLinkItems=false, and this appears to have no effect; versions-maven-plugin still scans all of my POMs for matching dependencies, throws up its hands, and quits. I've also tried setting searchReactor to false for that property in the plugin configuration. It appears that the plugin (1) incorrectly scans the dependencies even when I've explicitly said to ignore them and (2) even filters out an explicit specific match.
Is there a simple way to rewrite a Maven property entry to a specific value, either forcing versions-maven-plugin to do what I say without validating for a version number or by using another goal? I'd prefer to avoid a tool like sed that doesn't understand XML (as I've seen recommended in a similar question), but I would be okay with a simple XPath manipulation.
Is there a simple way to rewrite a Maven property entry to a specific value
Since version 2.5 we can use set-property (documentation):
mvn versions:set-property -Dproperty=your.property -DnewVersion=arbitrary_value
As documented, the set-property goal does not perform any 'sanity checks' on the value you specify, so it should always work, but you should use with care.
The newVersion parameter is badly documented (as is most of this plugin). By checking the integration tests, I see it takes a Maven version range not a simple version number. Also, it does not allow you to provide any value - it must be a valid one that Maven can resolve. The parameter would be better if it was called constrainRange
For anyone else in future, try this:
mvn versions:update-property -Dproperty=frontend.version -DnewVersion=[0.13.2]
If you need to update to a snapshot make sure you set the property allowSnapshots to true
mvn versions:update-property -Dproperty=frontend.version -DnewVersion=[0.13.2] -DallowSnapshots=true
How to update property in existing POM:
Try to use filtering in maven-resource-plugin:
specify version in property file;
add custom filter with path to this file (in child pom.xml, where dependency should be injected);
update version in property file;
run build.
Advantages:
it should work;
version is specified only once;
property file could be added under version control;
process-resources is one of the first maven lifecycle steps.
Disadvantages:
well, pom.xml still uses placeholder;
additional work to automatically update property file from initial build (too complicated, I suppose there should be easier solutions).
How to provide propery on build time:
You could specify any property by build parameter.
For example, I have property in my pom.xml like:
<properties>
<build.date>TODAY</build.date>
</properties>
To change it during build I simply use parameter:
mvn compile -Dbuild.date=10.10.2010
I'm pretty sure it will work for version as well. Also, properties from top level projects are inherited by childs.
I had the same problem and found nothing that changes pom properties in the file.
I ended up using sed like you suggested:
cat pom.xml | sed -e "s%<util.version>0.0.1-SNAPSHOT</util.version>%<util.version>$bamboo_planRepository_branch</util.version>%" > pom.xml.transformed;
rm pom.xml;
mv pom.xml.transformed pom.xml;
The following applies to versions:update-properties goal. I think the same would apply to versions:update-property.
The goal by default only works if a corresponding property definition and dependency declaration appear in the same POM file.
If, say, the property is defined in a project POM but used in a dependency declaration in a module POM, then the following config is required in the project POM for automatic update via Versions plugin.
<properties>
<my.version>3.7.11</my.version>
</properties>
...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<properties>
<property>
<name>my.version</name>
<dependencies>
<dependency>
<groupId>com.acme.test</groupId>
<artifactId>demo-arti</artifactId>
</dependency>
</dependencies>
</property>
</properties>
</configuration>
</plugin>
</plugins>
</build>
The plugin configuration comes into action when the Versions maven plugin runs against the POM and attempts to update the property. The configuration tells the Versions plugin that the property will be used for the stated dependency "in a POM somewhere" even if not in the present POM.
I had issue with update-property, but managed to make it work with set-property:
mvn versions:set-property -Dproperty=mypropery -DnewVersion=myvalue
When you define your property in the pom.xml you must declare as an interval if you want that update-property works.
I mean, sure your frontend.version is defined as follow:
<frontend.version>0.13.1</frontend.version>
Then the plugin when you set -DnewVersion=0.13.2 does not recognise the value as valid value. Instead of if you define as a interval, the plugin works.
<frontend.version>[0.13.0,0.13.2]</frontend.version>
In one of my test i get the following result:
mvn versions:update-property -Dproperty=absis.version -DnewVersion=[2.20.4] -X
[DEBUG] Property ${test.version}: Set of valid available versions is [2.19.0-RC-REVISION-1, 2.19.0-RC0.1, 2.19.0-RC0.2, 2.19.0-RC0.3, 2.19.0-RC0.4, 2.19.0-RC0.5, 2.19.0-RC0.6, 2.19.0-RC0.7, 2.19.0-RC1, 2.19.0-RC2, 2.19.0-RC3, 2.19.0, 2.19.0-revision, 2.19.0-revision2, 2.19.0.2, 2.19.1, 2.19.2, 2.19.3, 2.19.4, 2.20.0-RC0, 2.20.0-RC0.1, 2.20.0-RC1, 2.20.0-RC2, 2.20.0-RC3, 2.20.0, 2.20.0-PRUEBA-VERSION, 2.20.0-PRUEBA-VERSION-2, 2.20.0-PRUEBA-VERSION-3, 2.20.0i-RC1, 2.20.0i-RC1.1, 2.20.0i, 2.20.0i.2, 2.20.1, 2.20.2, 2.20.4, 2.20.5, 2.20.5-LT, 2.20.5.1, 2.20.6i-RC1, 2.21.0-RCtest1, 2.21.0-RCtest2]
[DEBUG] Property ${test.version}: Restricting results to [2.20.4,2.20.4]
[DEBUG] Property ${test.version}: Current winner is: 2.20.4
[DEBUG] Property ${test.version}: Searching reactor for a valid version...
[DEBUG] Property ${test.version}: Set of valid available versions from the reactor is []
[INFO] Updated ${test.version} from [2.19.0,2.21.0-SNAPSHOT] to 2.20.4
Buy you need to change the property value to a range.
It's a shame because I can't use range in my poms definition.

Reading Properties file from POM file in Maven

Why is this NOT working ? How to pick the version numbers from the properties file.
Reading properties in pom.xml
<project>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
</execution>
<configuration>
<files>
<file>dev.properties</file>
</files>
</configuration>
</executions>
</plugin>
</plugins>
</build>
</project>
In dev.properties
org.aspectj.aspectjrt.version=1.6.11
Dependency in pom.xml
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj.aspectjrt.version}</version>
</dependency>
Error : dependency must be a valid version
When you start up Maven from the command line, it goes through a number of stages. Here is a pseudo description of these stages, I am intentionally simplifying the exact sequencing (with the risk of saying things that are slightly incorrect/out-of-order) so that you can see why what you are trying to do cannot work.
First it parses your command line, any properties defined on the command line using the -Dname=value are injected into the MavenSession
The reactor defining command line options are checked to decide what the list of projects to build (also known as the reactor) should be. -N means build only the root pom.xml, -pl allows specifying a list of modules to build, -am and -amd allows adding upstream or downstream, respectively, modules from those specified by -pl. Maven has not parsed any pom.xml files at this point in time.
The -P profile activation rules are parsed to see what profiles to activate.
Now Maven has enough knowledge to start parsing the pom.xml files. It starts by loading and parsing the root pom.xml, i.e. the one in the current directory (or if you specified an alternative pom.xml with -f then that one). This initial parse is just concentrating on figuring out the list of projects to build. Profile activation is only considered in so much as it may affect the list of <modules> that are available. The Group Id, Artifact Id, Version and Packaging coordinates in the pom.xml cannot contain properties because the parsing of the properties in the pom.xml has not taken place at this point in time. (The observant reader will also see that this also explains why you cannot activate profiles based on properties within the pom.xml, as only system properties have been parsed at this stage)
Once the set of projects has been validated, Maven now does some more parsing of those pom.xml files to construct the list of build extensions (if any) and the list of plugins. At this stage the parsing requires evaluation of the <properties> in each project, so this is when these get evaluated and "injected" into the effective model. Thus you can use system properties and pom properties to define the coordinates and additional dependencies within (xpath) /project/build/extensions, /project/build/pluginManagement/plugins/plugin, /project/build/pluginManagement/plugins/plugin/dependencies, /project/build/plugins/plugin and /project/build/plugins/plugin/dependencies.
Now Maven starts parsing the list of goals and phases specified on the command line. Partially specified goals are evaluated for a match against the list of plugins. The match must be unique for all the projects that the plugin goal will be executed against (i.e. if it is an aggregator goal, the match is only required at the root, but for all other "normal" goals, the plugin short name must be the same plugin for all projects). Lifecycle phases must be from one of the default lifecycles, or from a lifecycle defined in a build extension.
From the parsed list of goals and phases, Maven constructs the build plan, i.e. what it is going to do on which projects and in what order. In order to do this Maven must parse the list of project dependencies defined in the reactor projects pom.xml files. This is because a dependency may be produced by another project within the reactor, thereby forcing a sequencing of project execution. Thus you can use system properties and pom properties to define the coordinates and additional dependencies within (xpath) /project/dependencyManagement/dependencies/dependency and /project/dependencies/dependency but note that at this point in time, no plugins have been executed.
Now that Maven has the build plan, it starts following that plan in the order that it constructed. If the first goal/phase on the CLI was a goal, then that goal will be invoked. If the first goal/phase was a phase from the default build lifecycle, then Maven will start with the initialize phase and execute all the plugins bound to that phase... continuing in a similar manner along the list of phases and then the list of projects. Note also that the initialize phase is only executed as part of the default build lifecycle. It is not executed on the default clean or default site lifecycles, and it is not executed on any custom lifecycles. (The observant reader will conclude that this highlights another problem with the technique that the question is attempting). Note: keep in mind that aggregator goals form a "break" in the reactor, so if you ask Maven to run clean package foo:bar site where foo:bar is an aggregator mojo goal, then clean package will be run against all the projects in the reactor, then foo:bar will be run against the root, then site will be run against all the projects in the reactor. In other words, the build plan will take the longest continuous run of non-aggregator goals & phases, split by longest continuous runs of aggregator goals.
Before it calls each mojo (i.e. goal bound to a phase or directly specified from the command line) Maven evaluates the pom.xml for the effective <configuration> of that mojo. At this point Maven has available the system properties, the properties specified in the pom and any properties injected into the MavenSession by previously executed mojos. Thus the <configuration> can reference any of those properties...
Aside
Now there is a caveat... if you say set (xpath) /project/build/directory to ${some-property-i-will-set-via-a-mojo} and then reference that from your <configuration>, well the sad news is that (xpath) /project/build/directory will have been evaluated into the effective pom.xml before any plugin execution, so ${project.build.directory} will have been given the literal value ${some-property-i-will-set-via-a-mojo} and that is of type java.io.File in the MavenProject so what you will actually have had happen is new File(project.getBaseDir(),"${some-property-i-will-set-via-a-mojo}"). If the <configuration> field you are injecting into is of type File, there will be no type conversion required, and hence the value will be injected straight in, and no property substitution will have taken place.
There are other edge cases, like the one outlined above, but in general property substitution will work with "mojo injected" properties (such as those provided by Mojo's Properties Maven Plugin) within the <configuration> sections. It will not work outside of those sections.
So here is Stephen's quick rule of thumb for the different property types:
System Properties
These work everywhere... but are extremely dangerous in /project/(parent/)?/(groupId|artifactId|version|packaging) as you have no control what so ever on what system properties will be defined when the project is pulled in as a transitive dependency. Use of ${...} expansion within /project/(parent/)?/(groupId|artifactId|version|packaging) should be considered as equivalent to driving a car at 200kph with a 30cm (12 inch) metal spike protruding from the steering wheel in place of an airbag... oh and no seat belt... and you've just had 10 units of Alcohol and two lines of cocaine.
pom.xml properties (and settings.xml properties)
These work in most places, but are never available within /project/(parent/)?/(groupId|artifactId|version|packaging) (as they have not been parsed when those fields are being evaluated) and are not available for consideration of the active profiles (again as they have not been parsed when profile activation is being evaluated)
Mojo injected properties
These work within <configuration> sections and may (due to the recursive interpolation of injected Mojo String parameters) work when used indirectly, but given the uncertainty involved, the recommendation is to restrict their use to the <configuration> section of plugins and reports only.
One final thing
Think about what happens when your project is listed as a dependency. If you had specified its dependencies by using a mojo to pull those from a .properties file on disk, Maven has no way to replicate that when your dependency has been pulled from the Maven repository. So Maven would be unable to determine the dependencies. Thus it could never work.
What you could do, is use an external system (e.g. ANT) to generate the pom.xml from a template with the versions replaced into that file. And then use the instantiated template to build.
This properties(dev.properties) file for build job.
<files>
<file>dev.properties</file>
</files>
For dependency you need add like below in your pom.xml file.
<properties>
<org.aspectj.aspectjrt.version>1.6.11</org.aspectj.aspectjrt.version>
</properties>

Resources