Running external Ant file from a parent pom - maven

I would like to run an Ant build.xml build from a parent POM.
This may look like this:
<project>
<groupId>my.group</groupId>
<artifactId>my-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>initialize</phase>
<configuration>
<tasks>
<ant antfile="build.xml"/>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
This works just fine unless I use this module as a parent POM.
The problem is in this line <ant antfile="build.xml"/>. While this POM is running as a parent POM there is no build.xml file available to the plugin.
How can I run an Ant script from a file (located in the parent POM) during all child build?
PS
I tried to package the build.xml under some classifier to make it available to the children builds. But I have no idea, how can I extract my packaged build.xml prior to the antrun:run.
PPS
The project structure:
<root>
+ Parent POM
| +- pom.xml
| +- build.xml
|
+ Component1
| + Child1
| | +- src/main/java
| | +- ...
| | +- pom.xml
| |
| + Child2
| +- src/main/java
| +-...
| +- pom.xml
|
+ Component2
+ Child3
| +- src/main/java
| +- ...
| +- pom.xml
|
+ Child4
+- src/main/java
+-...
+- pom.xml
As a bonus: I also would like to know the answer for the situations, where the parent POM get built and deployed independently (not knowing own child) and children get built having only access to the parent deployed artifacts (not the source code).

To avoid the FileNotFoundException you could use a configured property as prefix of the ant build file. Such a property would be empty on the parent pom while would have the right prefix (i.e. relative path to parent folder) in the required modules.
For instance, in your parent POM your configuration would look like:
<properties>
<ant.build.dir.prefix></ant.build.dir.prefix>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>initialize</phase>
<configuration>
<tasks>
<ant antfile="${ant.build.dir.prefix}build.xml" />
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Note the ${ant.build.dir.prefix} prefix added to the ant invocation. By default it will be empty, which means file would be supposed to be located in the same directory as the pom.
However, in modules you would just need to override the value of the property, as following:
<properties>
<ant.build.dir.prefix>..\</ant.build.dir.prefix>
</properties>
Or any other relative path in the folders hierarchy.
At runtime, the value will be replaced and as such the path to the ant file will dynamically change, enforcing a common and centralized configuration of the ant run (in the parent pom) and a specific path configuration in modules (via a property prefix).
I just tested both cases (your configuration and the prefixed one) in a sample project with an echo ant task, being able to reproduce your issue and to fix it as suggested above.

Related

How to setup Maven Archetype to generate module project at same level as parent project?

I want to create a maven archetype which should generate child module projects at the same level as parent project. So the structure will look like -
- parent
|_ pom.xml
|_ <rest-of-the-files>
- child1
|_ pom.xml
|_ <rest-of-the-files>
- child2
|_ pom.xml
|_ <rest-of-the-files>
The parent pom.xml will have modules like -
<modules>
<module>../child1</module>
<module>../child2</module>
</modules>
Is there any way to achieve this?
See answer to Error installing a multimodule archetype created with mvn archetype:create-from-project:
It looks like the archetype plugin doesn't support flat layout for multi-module projects.
You can use the following (agreed, a bit cumbersome) workaround:
Create your projects as:
+- parent
+- pom.xml
+- ...
|
+- child1
| +- pom.xml
| +- ...
|
+- child2
+- pom.xml
+- ...
Create another project in parent/src/main/resources:
+- parent
+- pom.xml
+- ...
+- src
+- main
+- resources
+- pom.xml
with the POM like:
...
<artifactId>move-modules</artifactId>
...
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>initialize</phase>
<configuration>
<target>
<echo level="info">Moving modules...</echo>
<move file="../../../../child1" tofile="../../../../../child1" failonerror="false" />
<move file="../../../../child2" tofile="../../../../../child2" failonerror="false" />
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Generate, install/deploy and use your archetype according to Maven Archetype Plugin, Advanced Usage/Archetype creation.
new/project/created/above/src/main/resources/move-modules $ mvn initialize
Adapt <module>s in your parent POM:
<modules>
<module>../child1</module>
<module>../child2</module>
</modules>

maven-javadoc-plugin target-directory of aggregated docs

I have an issue concerning the target directory of aggregated javadocs.
What I have is:
A maven project containing several modules. It looks a bit like the one used as example here
Project
|-- directory_to_contain_docs/
|-- pom.xml
|-- Module1
| `-- pom.xml
|-- Module2
| `-- pom.xml
`-- Module3
`-- pom.xml
I can't get it done to make javadoc generate the documentation in the directory named "directory_to_contain_docs".
This is what I tried:
I call the generation with "mvn javadoc:aggregate". And this is a part of the pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
<configuration>
<!-- Default configuration for all reports -->
<failOnError>false</failOnError>
<destDir>${basedir}/directory_to_contain_docs</destDir>
<!-- as there are lots of incorrectly documented sources -->
<additionalparam>-Xdoclint:none</additionalparam>
</configuration>
<executions>
<execution>
<id>aggregate</id>
<goals>
<goal>aggregate</goal>
</goals>
<phase>site</phase>
<configuration>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
The javadoc is always generated in {project}/target/site/apidocs, the generation creates the complete path given in destDir beneath that directory. I am looking for a way to have the whole docs somewhere else.
Is there a chance to achieve that?
Thanks,
Ishiido
Don't know why I did not see it... The missing link is
configuration/reportOutputDirectory.
It specifies the directory where the documentation is generated. It may be specified further by destDir.

How to create a .jar out of multiple jars using Maven Plugin

I have a project which has multiple .jar files in it. To add this as a dependency, I need to turn all these jars into one big jar. So far I have come until:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>mainProjects</groupId>
<artifactId>mainProjects.master</artifactId>
<relativePath>../pom.xml</relativePath>
<version>1.0.0-SNAPSHOT</version>
</parent>
<groupId>mainProjects</groupId>
<artifactId>sampleModule1</artifactId>
<name>sampleModule1</name>
<version>1.0.0.qualifier</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>Sample1.jar</include>
<include>Sample2.jar</include>
</includes>
</artifactSet>
<finalName>${project.artifactId}-${project.version}-final</finalName>
<outputDirectory>${project.artifactId}/build</outputDirectory>
<shadedArtifactAttached>false</shadedArtifactAttached>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
This creates the final jar, however, inside there are no content from the other jars (sample1.jar and sample2.jar) as there should be. I have looked into the documentation of the plugin, however all they did was to do it via class files, not jars. So I don't know how to proceed from now on.
Any thoughts?
Update:
So in order to make it clear, hereby I share the project structure that I have:
+- mainProjects
| +- pom.xml
| +- mainProject1
| | +- pom.xml
| | +- src
| +- mainProject2
| | +- pom.xml
| | +- src
| +- group1
| | +- pom.xml
| | +- sampleModule1
| | | +- pom.xml
| | | +- build
| | | +- sample1.jar
| | | +- sample2.jar
| | | +- sample3.jar
| | | +- sample4.jar
| | | +- sample5.jar
| | | +- sample6.jar
| | +- sampleModule2
| | | +- pom.xml
| | | +- src
Now, I want to be able to use sampleModule1 as a dependency in the pom.xml of mainProject1 as a jar, like this:
<dependency>
<groupId>group1</groupId>
<artifactId>sampleModule1</artifactId>
<version>1.0.0.qualifier</version>
<scope>system</scope>
<systemPath>sampleModule1/build/${project.artifactId}-${project.version}-final.jar</systemPath>
</dependency>
to achieve this, I need to compile all the jars into one jar, so that I can add it by using one systemPath. I found this which shows an example of how to include multiple files into one. However, in the example they are not jars, but rather classes and others. Now here, I am trying to achieve the same, but with only jars.
There are two ways to solve your problem! If you just want to to add files into your jar, you can use the resources tags to add them
<build>
<resources>
<resource>
<filtering>false</filtering>
<directory>lib</directory>
<includes>
<include>*.jar</include>
</includes>
</resource>
</resources>
</build>
This now puts all jar files from you lib folder into the main jar. The root folder is the folder from which you invoked the corresponding pom.xml. With this you can add arbitrary files to you jar. For a complete syntax reference take a look here.
The other way and maybe the most convenient way is to use the maven-shade-plugin this allows you to copy almost everything into you final jar.
<?xml version="1.0" encoding="UTF-8"?>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>groupid:artifactid_a</include>
<include>groupid:artifactid_b</include>
</includes>
</artifactSet>
<filters>
<filter>
<artifact>*:*</artifact>
<includes>
<include>resources/*.png</include>
</includes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
The artifactSet parts allow you to reference jar from within you local repro to be included just by mentioning their groupid and artifactid
This will include the content like class files, manifest etc. and also the folder structure) of the mentioned artifact (from you local repro) into you jar.
If you want to include other arbitrary files into you jar you can use the filter tag of the plugin which allows you to specify files and file-patterns directly. For a complete syntax reference take a look here.
P.S.: If you want to exclude certain files you can replace the include tag by an exclude tag ;-)

How to use checkstyle:check in a multi module project

I'm trying to use Maven Checkstyle plugin in a multi module project.
The default setting for <sourceDirectories> (where the plugin to start looking for code) is ${project.compileSourceRoots}. This resolves to [C:\workspace\projectname\src\main\java] in my case, i.e. a List<String>.
Now, that default path is of no value to me, since my code resides in different places, like so: [C:\workspaces\projectname\module1\src\main\java]. Hence, I need to change <sourceDirectories> to a list of directories where my code actually is.
So far, so good...
The problem is that <sourceDirectories> expects a List<String>. I tried the following:
<sourceDirectories>
<sourceDirectory>pathToCode1</sourceDirectory>
<sourceDirectory>pathToCode2</sourceDirectory>
</sourceDirectories>
... but that didn't work. It will take the default path. (Moreover, <sourceDirectory> is deprecated!)
Having only one <sourceDirectory> (without the surrounding <sourceDirectories>) does work, but <sourceDirectory> only takes one path and you can't have more than one <sourceDirectory>. So, no cigar. Also, keep in mind <sourceDirectory> is deprecated.
I also tried various other methods of providing a List<String> to <sourceDirectories>, but alas, no progress. Here are some examples:
<sourceDirectories>[pathToCode]</sourceDirectories>
<sourceDirectories>pathToCode</sourceDirectories>
<sourceDirectories>{pathToCode}</sourceDirectories>
<sourceDirectories>{[pathToCode]}</sourceDirectories>
<sourceDirectories>{{pathToCode}}</sourceDirectories>
<sourceDirectories>{{{pathToCode}}}</sourceDirectories>
Is there another way of (directly, without "sub-tags") providing a List<String> to maven?
Is the plugin broken?
Have I missed something?
Edits below
My project structure:
MyProject
|-- pom.xml <-- plugin runs fine here
|-- domain-module
| |-- src
| | `-- main
| | `-- com/example/hello...
| | |-- TheCode.java
| | `-- resources
| | |-- checkstyle.xml
| | `-- LICENSE.TXT
| `-- pom.xml
|-- poms
| |-- parent
| | `-- pom.xml <-- this is my parent pom
My parent pom
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>${checkstyle.version}</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.16</version>
<dependencies>
<dependency>
<groupId>com.example.hello</groupId>
<artifactId>domain-module</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>validate</id>
<phase>validate</phase>
<configuration>
<configLocation>domain-module/src/main/resources/checkstyle.xml</configLocation>
<encoding>UTF-8</encoding>
<consoleOutput>true</consoleOutput>
<failsOnError>false</failsOnError>
<failOnViolation>true</failOnViolation>
<violationSeverity>warning</violationSeverity>
<logViolationsToConsole>true</logViolationsToConsole>
<skip>false</skip>
</configuration>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<...>
</build>
</pluginManagement>
</plugins>
Since version 2.13 the use of sourceDirectories is broken (https://issues.apache.org/jira/browse/MCHECKSTYLE-260).
With 2.12 it works. Andreas Dangel mentioned in Jira:
The configuration described here
Checkstyle - Exclude folder
still works. Then the exclusion happens in checkstyle, rather than in
maven-checkstyle-plugin.

Maven multi project issue

I am having some issues with my multi-project Maven project.
The problem is the following:
I have a project that organized in the following way:
root
+-- pom.xml
!
+-- module1
! +-- pom.xml
+-- module2
+-- pom.xml
Where module2 depends on module1.
Module1 is packaged as war, it also generates jar file that module2 depends on.
Everything is fine whenever the changes are only in module2 i.e. module1.jar is already in remote repo, however whenever there are changes in both modules during mvn clean release:clean release:prepare release:perform I get an error saying that module1.jar could not be found in remote repo.
So to fix that I have added maven-install-plugin to the Module1's pom file like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<file>${project.build.directory}/${project.artifactId}-${project.version}.jar</file>
<!-- <packaging>jar</packaging> -->
</configuration>
<executions>
<execution>
<id>install</id>
<phase>compile</phase>
<goals>
<goal>install</goal>
</goals>
</execution>
</executions>
whenever i comment out <packaging>jar</packaging> it tries to install Module1 jar file into local repo as war file (I am guessing that by default it would pick up packaging from the POM file). So i get something like this:
[INFO] [INFO] [jar:jar {execution: creation}]
[INFO] [INFO] Building jar: ${project.build.directory}/${project.artifactId}-${project.version}.jar
[INFO] [INFO] [install:install {execution: install}]
[INFO] [INFO] Installing ${project.build.directory}/${project.artifactId}-${project.version}.jar to <.m2_local_repo>/<proper_path>/${project.version}/${project.artifactId}-${project.version}.war
However if i un-comment <packaging>jar</packaging> it complains that i am attempting to set a read-only property.
So the question i have, how can i install jar file to my local repo during my build?
Updating the question w/ some parts of module1 and module2 pom files:
module2 pom parts:
<parent>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>1.01-SNAPSHOT</version>
</parent>
<artifactId>module2</artifactId>
<version>1.08-SNAPSHOT</version>
<packaging>war</packaging>
...
<dependency>
<groupId>...</groupId>
<artifactId>module1</artifactId>
<version>4.18-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
module1 pom:
<parent>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>1.01-SNAPSHOT</version>
</parent>
<artifactId>module1</artifactId>
<version>4.18-SNAPSHOT</version>
<packaging>war</packaging>
i added install plugin to make sure that module1.4.18.jar will be installed locally so that module2.0.18.war will be able to use module1.4.18.jar
eventually i went with <goal>install-file</goal> instead of <goal>install</goal>
this way i was able to specify proper packaging (it turns out that packaging on install goal is read only, but you can override it for install-file)
so this is what i end up with:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>install</id>
<phase>compile</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${project.build.directory}/${project.artifactId}-${project.version}.jar</file>
<packaging>jar</packaging>
</configuration>
</execution>
</executions>
</plugin>
#MariuszS and #WIll- thank you for your insight on this matter
I think your project has wrong configuration (not in maven way). Proper configuration looks like this
* parent (root)
* module1 (war1)
* module2 (war2)
* jar (shared code from war2)
Move your code from war to separate module and add this module as depdency to both war modules.

Resources