How to set the Maven artifactId at runtime? - maven

I would like to define the artifactId in a POM at runtime. I am aware from answers to this question that this is bad practise and Maven archetypes should be used instead, but I would really like to know if it is possible at all.
Currently I have a POM with an artifactId like this:
<artifactId>myproject${var}</artifactId>
and I can successfully build the project by setting the variable on the command line:
mvn install -Dvar=justatest
Now is it possible to change this input variable at runtime? For example convert it to uppercase (e.g. with the gmaven-plugin) or similar?

You cannot change the artifactId at build-time. It is part of the Maven coordinates (groupId:artifactId:version) so it must be fixed.
All other parameters you could change during the build with the maven-antrun-plugin.
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>touppercase</id>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<property name="varUpper" value="${var}"/>
<script language="javascript"> <![CDATA[
property = project.getProperty("varUpper");
project.setProperty("varUpper", property.toUpperCase());
]]> </script>
</target>
<exportAntProperties>true</exportAntProperties>
</configuration>
</execution>
</executions>
</plugin>
After this execution, Maven will have a new property called ${varUpper} that is uppercased ${var}. You need to set the correct phase to the snippet above to match your build process.

Related

How to invoke specific execution

I am trying to replace maven exec with MavenInvokerPlugin because of problems on Jenkins with forwarding the maven settings file.
So in bash it looks straight:
mvn dependency:copy-dependencies#resolve-maven-deps
My translation to MavenInvokerPlugin configuration is
<plugin>
<artifactId>maven-invoker-plugin</artifactId>
<version>3.0.1</version>
<configuration>
<projectsDirectory>${project.basedir}/src/main/docker</projectsDirectory>
<localRepositoryPath>${project.build.mavenDependencies}</localRepositoryPath>
<goal>dependency:copy-dependencies#resolve-maven-deps</goal>
</configuration>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>run</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
</plugin>
It looks like that execution id is completely ignored, because I tried random strings and mvn builds the project with success.
mvn dependency:copy-dependencies#asdfasdfa
So I'd like to know whether this feature is supported at all and what I am doing wrong.
P.S. I know that calling maven out of maven is anti pattern, but here is exactly that rare case when there is no other way.
After looking at projects using maven invoker I figured out the trick.
goal tag is not used, instead provide invokerPropertiesFile:
<pom>${project.basedir}/xxx/pom.xml</pom>
<invokerPropertiesFile>${project.basedir}/invoker.properties</invokerPropertiesFile>
content of the file:
invoker.goals=compile -P resolve-maven-deps

How can I generate a maven property that's a UUID?

I have a file in my build that I want to put a UUID in every time a build is ran. I use maven's #my.property# to do this for other properties like project.version. What's the simplest way to have maven insert a universal unique identifier (UUID) similar to java.util.UUID does? (I'd rather not write a plugin if I can avoid it)
Edit: Actually, the buildNumber is not random per build but rather the git commit hash of the build. Coincidentally, I also needed this so it's helpful, but does not answer the question.
It appears the 'buildNumber' property does what I need. I'm going forward with that.
Maven property:
[echoproperties] buildNumber=fb08b44b310c489f5b170842d3aac3c5eb5a6f7b
In my file:
"uid": "fb08b44b310c489f5b170842d3aac3c5eb5a6f7b",
I used this plugin that prints all available properties (careful as some might differ - like env.* - between environments:
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<property environment="env" />
<echoproperties />
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
https://florianlr.wordpress.com/2012/04/24/16/

Read a file into a Maven property

Is it possible to read a file and store the entire contents into a Maven property?
I'm trying to generate some custom JavaDocs, and they have an option to set a header, but it has to be a string, not a file name (for some reason). I obviously don't want to put a bunch of HTML into my pom.xml, so I need a way to read my header.html as a Maven property.
Is this possible? I'm not able to find a standard way, but it seems like a Maven plugin might do this.
Apparently Ant has what I want, but I'd prefer something lighter weight than the Ant task.
See this question on SO. And here is the properties-maven-plugin.
If you'd like not to use .properties file, than I can suggest to use the Groovy plugin and a small script that I've written:
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<properties>
<header_file>header.html</header_file>
</properties>
<source>
def file = new File(project.properties.header_file)
project.properties.header_content = file.getText()
</source>
</configuration>
</execution>
</executions>
</plugin>
After execution of this plugin, you should be able to refer to ${header_content} property that contains header.html file contents.

Buildnumber not getting propagated down to childern from parent

I am using the buildnumber-maven-plugin in my parent pom to create a build number. This works fine. However, I need to have the ${buildNumber} property in my child. I have added antrun ECHO for that property in my child and it is not there. How can I propagated that property down to children?
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<inherited>false</inherited>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
<configuration>
<buildNumberPropertiesFileLocation>buildnumber.properties</buildNumberPropertiesFileLocation>
<format>{0,number,integer}</format>
<items>
<item>buildNumber0</item>
</items>
</configuration>
</plugin>
I found the issue. This may be a bug in the build number plug in. The property I use for the build number (the default name or one I set) does not get propagated down to the child project unless I add in
<getRevisionOnlyOnce>true</getRevisionOnlyOnce>
After adding this line in my pom for the build number plugin, all worked fine. Seems like if you don't have this line in the pom for that plugin it whips out the build number property upon completion of the Parent. Not sure. But all is working now.
Try to remove
<inherited>false</inherited>

Integrating ant resource generation targets into a Maven build

I'm currently working on a fairly large project that has been migrated from Ant to Maven. There are no problems with the actual build process (it compiles and packages the source code fine).
The problem is that I also have a lot of targets that generate additional resources for the project (compile LessCSS, generate & upload documentation, generate tld files for custom tags and functions etc.). I am not sure how I should handle these tasks. Let's take the target that builds CSS&JS as an example (the others are more or less similar, but not connected). It looks like this (simplified):
<target name="build.css_js">
<concat destfile="${webapp.dir}/scripts/main.js">
<fileset dir="${webapp.dir}/scripts/src" includes="*.js"/>
</concat>
<!-- build css files from less sources -->
<taskdef name="lesscss" classname="com.asual.lesscss.LessEngineTask" classpathref="libraries" />
<lesscss input="${webapp.dir}/syles/src/input.less" output="${webapp.dir}/styles/output.css" />
</target>
In the pom.xml I have the following plugin set up:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>generate-resources</phase>
<configuration>
<tasks>
<echo message="Hello World from pom.xml"/>
<ant target="build.css_js"/>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
The dependencies I'm using are no longer in our SVN repository (since they are managed by Maven), so I switched the libraries variable to point to the Maven repo:
<property name="lib.dir" location="${env.HOMEPATH}/.m2/repository" />
This is not good, as that path may be valid only on my machine. I don't know any other way to reference the libraries from the Maven repository and I need them to run the ant targets.
Is my approach ok or is there a better way of doing things?
How do I get over the library problem?
Some resources are needed when packaging the project but some are not. Is there a lifecycle phase that is out of scope for compile/package? I found the site lifecycle which I think fits my needs.
Ideally, I should give up on the ant build file altogether, but I'm not sure it's worth the effort of making the scripts run as maven plugins (I currently have no idea how to do that). What do you think about this?
I'm new to Maven so any suggestions are appreciated.
Generally embedding antrun calls is not ideal, but if you've not found a suitable plugin to do what you need then I wouldn't worry about it. If the processing is fairly simple it is actually quite easy to embed it in a Maven plugin yourself, see this example for help getting started.
If you are going with antrun, and the dependency jars have already been installed to your Maven repository, you can configure the antrun plugin to use those jars in its execution by adding them as dependencies of the plugin configuration. This means the dependencies will be resolved and available for use, but not be visible to your project (useful to help avoid accidental inclusion). To then access them in a portable way you can use:
<property name="lib.dir" location="${settings.localRepository}" />
Alternatively you can use some of the other properties available to expose the Maven classpaths to the antrun plugin, for example ${maven.compile.classpath} See the antrun documentation for more details.
If you have multiple discrete executions for ant, you can configure them individually in the antrun plugin and specify a suitable id for each one. The example below shows two executions, both bound to the process-resources phase. Of course you need to supply some actual goals.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>build-css</id>
<phase>generate-resource</phase>
<configuration>
<target>
...
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>build-js</id>
<phase>generate-resource</phase>
<configuration>
<target>
...
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>some.group.id</groupId>
<artifactId>artifactId</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>another.group.id</groupId>
<artifactId>anotherId</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>

Resources