Creating an Archetype From POM: Property is Missing - maven

I created a Maven archetype and want to create an example project of it in my repository, which seems to be an unusual use-case.
Since I don't want to create the archetype manually, I added the following execution:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-archetype-plugin</artifactId>
<configuration>
<archetypeGroupId>my.company.archetypes</archetypeGroupId>
<archetypeVersion>${project.version}</archetypeVersion>
<groupId>org.acme</groupId>
<version>0.1.2-SNAPSHOT</version>
<interactiveMode>false</interactiveMode>
</configuration>
<executions>
<execution>
<id>archetype-one</id>
<goals>
<goal>generate</goal>
</goals>
<phase>package</phase>
<configuration>
<archetypeArtifactId>archetype-one</archetypeArtifactId>
<artifactId>one</artifactId>
<package>org.acme.one</package>
</configuration>
</execution>
</executions>
</plugin>
This leads to the following exception:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-archetype-plugin:2.2:generate (archetype-one) on project examples: Archetype my.company.archetypes:archetype-one:0.9.0-SNAPSHOT is not configured
[ERROR] Property groupId is missing.
[ERROR] Property artifactId is missing.
[ERROR] Property package is missing.
Which is just not true, since I've defined all of these. At least the IDE proposes these tags on that position. Moving the configuration tags around doesn't help either.
So I checked the source code of generate, and lo and behold, the target GAVs aren't present.
How do I define them when generating an archetype directly from another pom.xml?

So I ended up using an entirely different Maven plug-in:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>archetype-one</id>
<goals>
<goal>exec</goal>
</goals>
<phase>package</phase>
<configuration>
<executable>mvn</executable>>
<arguments>
<argument>archetype:generate</argument>
<argument>-DarchetypeGroupId=my.company.archetypes</argument>
<argument>-DarchetypeVersion=${project.version}</argument>
<argument>-DgroupId=org.acme</argument>
<argument>-Dversion=0.1.2-SNAPSHOT</argument>
<argument>-DinteractiveMode=false</argument>
<argument>-DarchetypeArtifactId=archetype-one</argument>
<argument>-DartifactId=one</argument>
<argument>-Dpackage=org.acme.one</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
And since I wanted to generate multiple archetypes, I put the first six arguments into a general <configuration> block, and appended the remaining three with <arguments combine.children="append">.

Related

Generate Javadoc for multimodule project

I have read everything I can find on solving this and my attempts still fail. The best I can do is to get the Javadoc of exactly one module to show up--the last one built. (For now, I'm not trying to bundle Javadoc into any JARs. I'm also not trying to do anything "site".) I just want to put Javadoc for easy access into a subdirectory under the project root.
Here's what's in my parent pom.xml:
<build>
<plugins>
.
.
.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<noqualifier>all</noqualifier>
<reportOutputDirectory>${user.dir}/documents</reportOutputDirectory>
<destDir>javadoc</destDir>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
What I'm putting into subordinate pom.xml files is identical to the above except for
<goals>
<goal>javadoc</goal>
</goals>
I have played with replacing the <execution> in the parent and sometimes subordinate pom.xml files with:
<execution>
<id>aggregate</id>
<goals>
<goal>aggregate</goal>
</goals>
</execution>
but it makes no difference.
I think the following configuration is the reason your reports get overwritten:
<configuration>
<reportOutputDirectory>${user.dir}/documents</reportOutputDirectory>
</configuration>
All module builds will be written to the same directory, hence overwriting the previous build.
The solution is to use the default output directory and configure the output directory for the aggregated javadoc instead. This way the reactor build will create javadoc output files in each module's target directory. These can then be used by the aggregate goal to be combined.
This can be done by configuring your parent POM as follows:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<!-- Default configuration for all reports -->
<noqualifier>all</noqualifier>
<destDir>javadoc</destDir>
</configuration>
<executions>
<execution>
<id>aggregate</id>
<goals>
<goal>aggregate</goal>
</goals>
<configuration>
<!-- Specific configuration for the aggregate report -->
<reportOutputDirectory>${user.dir}/documents</reportOutputDirectory>
<destDir>javadoc</destDir>
</configuration>
</execution>
...
</executions>
</plugin>
...
</plugins>
</build>
(there is no need for any additional configuration in the module POM files)
The aggregated javadoc can now be created by running
mvn compile javadoc:javadoc javadoc:aggregate
(note that the compile or package goal is required for reactor to resolve inter-module dependencies)

why list the goals of a plugin without binding to a phase?

Please consider this pom excerpt taken from jacoco example ( http://www.eclemma.org/jacoco/trunk/doc/examples/build/pom-it.xml)
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.5-SNAPSHOT</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>default-prepare-agent-integration</id>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
</execution>
<execution>
<id>default-report</id>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>default-report-integration</id>
<goals>
<goal>report-integration</goal>
</goals>
</execution>
<execution>
<id>default-check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<!-- implmentation is needed only for Maven 2 -->
<rule implementation="org.jacoco.maven.RuleConfiguration">
<element>BUNDLE</element>
<limits>
<!-- implmentation is needed only for Maven 2 -->
<limit implementation="org.jacoco.report.check.Limit">
<counter>COMPLEXITY</counter>
<value>COVEREDRATIO</value>
<minimum>0.60</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.16</version>
<executions>
<execution>
<id>default-integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Now I know that you can bind a plugin's goal to a maven phase, that is run that goal when maven executes a specific phase.
What is the point of just listing the integration-test goal for the maven failsafe plugin without binding it to something?
The same as for jacoco report and others goal? I don't think you can force the plugin to execute just those listed goals right?
Many thanks
The point is that a plugin can define default life cycle phases where the appropriate goal is bound to (many plugins do this). In this cases you don't need to specify the life cycle phase within the pom file explicitly.
For example the maven-failsafe-plugin has a goal integration-test. This goal has a default binding to the integration-test life cycle phase. Here an excerpt from the documentation:
Description:
Run integration tests using Surefire. Attributes:
Requires a Maven project to be executed.
Requires dependency resolution of artifacts in scope: test.
The goal is thread-safe and supports parallel builds.
Binds by default to the lifecycle phase: integration-test.
That's the reason why you don't need to give a life cylce phase in the configuration like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18.1</version>
<executions>
<execution>
<id>default-integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
</executions>
</plugin>
The same is meant for the jacoco maven plugin.
If I understand correctly, M2E will execute the plugin goal during workspace full or incremental builds.
The following article may shed some light:
http://eclipse.org/m2e/documentation/m2e-execution-not-covered.html
You are correct that, on command line, you would not be able to specify the goal, since it is a plugin goal and not tied to a phase. This could be an oddball usage specifically for M2E integration.

How to register a custom built jar file as maven main artifact?

I have a project expected to deliver a jar file:
<packaging>jar</packaging>
but the jar is built in a custom way, so the default packaging done with jar:jar has been disabled
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.2</version>
<executions>
<execution>
<id>default-jar</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
but then when I want to apply shade:shade on the existing jar I get an error
The project main artifact does not exist.
I assume that maven doesn't know about the .jar file created by my custom tool. How to let it know, because antrun attachArtifact doesn't work
<attachartifact file="./bin/classes.jar" classifier="" type="jar"/>
the error I get is
An Ant BuildException has occured: org.apache.maven.artifact.InvalidArtifactRTException: For artifact {:jar}: An attached artifact must have a different ID than its corresponding main artifact.
So this is not the method to register main artifact... Is there any (without writing custom java plugin)?
Thanks,
Lukasz
I checked the sources of JarMojo and it gave me an idea how to solve it with Groovy (via gmaven)
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>set-main-artifact</id>
<phase>package</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
project.artifact.setFile(new File("./bin/classes.jar"))
</source>
</configuration>
</execution>
</executions>
</plugin>
and it works!:)
Something like this
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>attach-artifacts</id>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>${basedir}/bin/classes.jar</file>
<type>jar</type>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
While your solution may work for a build to the install+ phase or where there are no dependencies in the reactor, in cases where only building to the compile or test phase the unpackaged classes won't be found by dependencies.
Building to compile happens when using plugins like the maven-release-plugin.
Extending your chosen solution to include identifying the unpacked classes during compile
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>set-main-artifact-compile</id>
<phase>compile</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
project.artifact.setFile(new File("./bin/classes"))
</source>
</configuration>
</execution>
<execution>
<id>set-main-artifact</id>
<phase>package</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
project.artifact.setFile(new File("./bin/classes.jar"))
</source>
</configuration>
</execution>
</executions>
</plugin>
By default the maven-install-plugin will use the identified artifact along the lines of
${project.build.directory}/${project.finalname}.jar
So another option might go something like this
<build>
<directory>bin</directory>
<outputDirectory>bin/classes</outputDirectory>
<finalName>classes</finalName>
</build>
We were having the same problem, with getting the "attached artifact must have a different ID than its corresponding main artifact" error. We found the solution in the following excellent blog post:
embed-and-run-ant-tasks-and-scripts-from-maven
As detailed in this section, you can fix the problem by adding a classifier so Maven can distinguish between the ant-built jar and the maven-built jar. Since you're using antrun attachartifact, you'd need this:
<attachartifact file="./bin/classes.jar" classifier="foo" type="jar"/>
Note you'll also need to include that classifier (along with groupId, artifactId and version) whenever you want to grab this jar as a dependency in other projects.

Maven: Extract dependency resources before test

I have a multimodule Maven project. One subproject hosts XSL/XML resource files. The other project hosts Java code that needs to use these files in its unit tests.
In the dependency's jar, the resources lie in the folder xml-resources.
I found this example and tried to change it for my needs:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>resource-dependencies</id>
<phase>process-test-resources</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<classifier>xml-resources</classifier>
<outputDirectory>${project.build.directory}/classes/xml-resources</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
This doesn't do anything when I run the process-test-resources phase. Am am sure that there are some errors in there - I do not see where I can specify the dependency the resources should be taken from, and <classifier> does not seem to actually specify the source where the resources should be copied from.
I'm lost here, can somebody tell me how to do this right?
Try something like this
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>resource-dependencies</id>
<phase>process-test-resources</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includeArtifactIds>my-artifact-id</includeArtifactIds>
<includes>foobar.txt, loremipsum.xml</includes>
<outputDirectory>${project.build.directory}/classes/xml-resources</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Have a look at the unpack-dependencies parameters for detailed explanation or further information.

In a Maven multi-module project, how can I disable a plugin in one child?

I have a maven multi-module project (boy, I've written that opening way too many times on this site). Almost all the modules (that is, the ones that have code in them) should run the maven-site-plugin to generate reports about code coverage, etc. These have a detailed shared configuration -- which reports to run, which files to cover/exclude for certain plugins, etc.
However, there are a few modules that deal with packaging -- running the assembly plugin to generate a tarball, etc. These gain nothing from running a site report -- there's no code to analyze, no tests to report on.
So I have a lot of modules that need to share plugin configuration, and a few modules that need to not run the plugin, preferably at all. I can do the former (share configuration) if I put the plugin in the <build> section of the parent POM, but I can't seem to turn off the plugin when I need to in this case. I can do the latter (avoid running the plugin) if I push configuration down to each module's own POM, but I can't figure out a good way to share the configuration information in this case.
Is what I want -- shared configuration, for a plugin that's sometimes disabled by a child module -- even possible? If so, how?
By "run the plugin", I'm assuming you mean that the plugin is bound to a lifecycle phase, and you'd like to unbind it in some modules. First, you could consider changing your POM inheritance so that the modules that don't need the plugins have one parent and the ones that do have a different parent. If you don't want to do that, then you can explicitly set the execution phase to "nothing" in a child module. E.g. if you had a parent pom configuration like this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>i-do-something</id>
<phase>initialize</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
... lots of configuration
</configuration>
</execution>
</executions>
</plugin>
Then in a child module, you could do this:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>i-do-something</id>
<phase/>
</execution>
</executions>
</plugin>
Because it's the same plugin and the same execution id, it overrides the configuration specified in the parent, and now the plugin isn't bound to a phase in the child project.
Ryan Stewart's answer works if execution that you wish to suppress in the parent pom is tagged with an id. If, however, the parent pom doesn't tag the execution with an id (and, of course, you can't edit that parent pom) then I found that doing the following suppresses the parent pom's action.
First set the phase of the execution to none
Create another execution, give it an id and do in it what you need it to do.
run mvn help:effective-pom to confirm that it has correctly suppressed what you needed suppressed from the parent pom.
Here's an example:
This is how my parent pom looked like:
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<inherited>true</inherited>
</plugin>
I needed to change the goal to jar-no-fork. Note that the execution in parent pom doesn't have an id that I could use to disable it. So here's what added to my child pom:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<phase>none</phase>
</execution>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
As a result this is how the effective-pom looks like:
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<phase>none</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<archive>
<compress>false</compress>
</archive>
</configuration>
</execution>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
<configuration>
<archive>
<compress>false</compress>
</archive>
</configuration>
</execution>
</executions>
<inherited>true</inherited>
<configuration>
<archive>
<compress>false</compress>
</archive>
</configuration>
</plugin>
This ensured that the goal jar never runs and only the goal jar-no-fork executes -- which is what I wanted to achieve.

Resources