Prevent maven module from being built with no activated profile - java

I have a multi-module maven project with parent POM. One child of project is customized for different environments by profiles and parent pom also build needed modules depending on selected environment (profile).
I want to prevent building (read as "to run mvn package" in child module) customized child project without profile activated, because there is no "generic" or "default" version for environment. Another words, I want to force developer to use environment-dependent profile.
Is it possible to do so?

Maven Enforcer is made just for this requirement. Simply add the required profiles.
<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<id>enforce-all-profiles-are-activated</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireActiveProfile>
<profiles>first,second</profiles>
</requireActiveProfile>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
</project>

Related

Fail Maven build if Maven property is not aligned to convention

Maven properties in pom.xml of Java repos have to be aligned to some convention for CI processes to work correctly.
For example:
<app-name.prop-name-version>X.X.X.X</app-name-version.prop-name-version>
Is there a way to fail maven builds if maven property is not aligned to convention?
I thought about developing maven plugin from scratch, but is there another way?
Maven Enforcer Plugin exactly does what you need. That has a lot of built-in rules like Require Property
According the documentation this rule can enforce the declared property is set and optionally fits for a regex rule.
<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M3</version>
<executions>
<execution>
<id>enforce-property</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireProperty>
<property>app-name.prop-name-version</property>
<message>"Project version must be specified."</message>
<regex>.*[...]$</regex>
<regexMessage>"Invalid format."</regexMessage>
</requireProperty>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
</project>

Configuring the maven java-docs plugin for multi module projects(Aggregate)

I would like to set up the maven java-docs plugin in my project to create an aggregated report that includes only some classes from some of the modules and output the report to a folder of choice.
I have already tried to work with the Maven documentation here however whats indicated there does not seem to work for me.
I have tried the following configuration in the past and ran it as:
mvn javadoc:javadoc, or even javadoc:aggregate with the following parent/child pom configurations:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.1.0</version>
<inherited>false</inherited>
<configuration>
<!-- Default configuration for all reports -->
</configuration>
<executions>
<execution>
<id>aggregate</id>
<goals>
<goal>aggregate</goal>
</goals>
<phase>package</phase>
<configuration>
</configuration>
</execution>
</executions>
</plugin>
I have used something like this in the past:
parent pom.xml
<pluginManagement>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</pluginManagement>
...
<build>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<!-- Default configuration for all reports -->
</configuration>
<executions>
<execution>
<id>aggregate</id>
<goals>
<goal>aggregate</goal>
</goals>
<phase>site</phase>
<configuration>
<skip>false</skip>
</configuration>
</execution>
</executions>
</plugin>
</build>
Desired child module pom.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<skip>false</skip>
<noqualifier>all</noqualifier>
<sourceFileIncludes>
<include>**\/\Class1.java</include>
<include>**\/\Class2.java</include>
<include>**\/\Interface3.java</include>
<include>**\/\Class4.java</include>
</sourceFileIncludes>
<reportOutputDirectory>${project.parent.basedir}/..</reportOutputDirectory>
<destDir>java-docs</destDir>
</configuration>
</plugin>
</plugins>
</build>
This configuration works fine if I am only generating from one single module, however once another child module is picked and configured as the one shown before, running mvn javadoc:aggregate continues to generate the docs for module 1 only, and module 2 gets ignored(or maybe even overriden)
Has anyone worked with a similar scenario, a multi module project structured like so:
ParentFolder
. . . module1
pom.xml
. . . module3
pom.xml
. . . module4
pom.xml
pom.xml
and have succeeded generating an aggregated java docs report using the maven java docs plugin, while excluding some classes and outputting the results to a folder of their choice?
Any help with this would be greatly appreciated!
Do you have one parent POM that contains both plugin config for the child POMs, and module definitions? If so, you may want to consider separating this POM into a separate aggregator (module definitions) and parent (anything else in the current POM that should be shared with children).
This answer goes into a lot more detail about Maven build order and why the behavior occurs.
The aggregator POM will also hold the configuration for child module data that should be aggregated, such as Javadoc.

How can I execute a plug-in, declared on parent pom.xml, on a spesific child pom.xml in Maven?

I am working on a Java EE project that consists of a parent project, and a list of sub-projects (modules). I have declared and configured a plug-in on the parent project's pom.xml within a <pluginmanagement> tag as follows:
Parent pom.xml
...
<pluginManagement>
<plugins>
<!-- inmem-db-plugin -->
<plugin>
<groupId>com.btmatthews.maven.plugins.inmemdb</groupId>
<artifactId>inmemdb-maven-plugin</artifactId>
<version>${version.inmemdb-plugin}</version>
<inherited>true</inherited>
<executions>
<execution>
<id>runDB</id>
<goals>
<goal>run</goal>
</goals>
<configuration>
<monitorKey>inmemdb</monitorKey>
<monitorPort>11527</monitorPort>
<daemon>true</daemon>
<type>derby</type>
<database>localDB</database>
<username>${user}</username>
<password>${pass}</password>
<sources>
<script>
<sourceFile> create - data.sql </sourceFile>
<sourceFile> create - table.sql </sourceFile>
</script>
</sources>
</configuration>
</execution>
<execution>
<id>stopDB</id>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
...
And then I have referenced it on the child's pom.xml file:
...
<build>
<plugins>
<plugin>
<groupId>com.btmatthews.maven.plugins.inmemdb</groupId>
<artifactId>inmemdb-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
...
From what I have read on the internet, this seems to be the right way of making sure that the specific plug-in will be used only on the specific module that i have referenced it.
But, When I run the mvn install command, the plug-in that it is needed to run wont show up at all. Is there anything else that it is needed to be done, in order for the plug-in to run on a spesific module only?
Thanks in advance.
UPDATE: I replaced the wrong <phase> values with valid ones, but still when I enclose the plugin with <pluginmanagement> the plugin wont run at all.
The parent > child configuration looks correct i.e. define the plugin in pluginManagement in the parent and then engage it in the child by including it build/plugins. But this looks incorrect to me: <phase>pre-test</phase>, pre-test is not a valid phase in the Maven lifecycle and hooking your plugin up to a non existent phase will prevent it from being run. I think the correct plugin configuration is:
<plugin>
<groupId>com.btmatthews.maven.plugins.inmemdb</groupId>
<artifactId>inmemdb-maven-plugin</artifactId>
<version>${version.inmemdb-plugin}</version>
<inherited>true</inherited>
<executions>
<execution>
<id>runDB</id>
<goals>
<goal>run</goal>
</goals>
<configuration>
...
</configuration>
</execution>
</executions>
</plugin>
I suspect you might have been using the 'phases' pre-test and post-test to start and stop the in-memory DB as/when your test phase starts and stops? If so, then the correct Maven phases are:
pre-integration-test
post-integration-test

Maven checkstyle https configuration

I have the following maven check style plugin configuration
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<configuration>
<consoleOutput>true</consoleOutput>
<configLocation>https://someUtl.com/file.xml</configLocation>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
Pay attention on
<configLocation>https://someUtl.com/file.xml</configLocation>
file.xml can be downloaded by browser, but it require a login and password. Is there a way to specify these login/password in maven or in plugin configuration?
Underneath, this uses Plexus which in turn pretty much does URL.openStream().
This answer shows how an Authenticator can be used for that in Java code, but I was unable to find a Maven equivalent for that. I'm inclined to say that it's not possible.
Alternatively, you might be able to download the file in a separate mojo execution, then point the configLocation to the downloaded file, which could be anywhere down your target folder.
I think that this answer gives a few nice ideas about how to download files in Maven. Their first is that if your file is a Maven artifact, you could use the Maven Dependency Plugin.
And then we come full circle, because if your Checkstyle configuration were to be contained in a Maven artifact, you would not have to set configLocation to a remote location, but you'd add that artifact as a dependency of your Checkstyle plugin execution. Since Maven defines everything in terms of dependencies, that is my way to go, and that is exactly how I set up my own Checkstyle configurations.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.totaalsoftware.incidentmanager</groupId>
<artifactId>checkstyle-config</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
<configuration>
<configLocation>checkstyle.config.xml</configLocation>
...
</configuration>
</plugin>
Clearly, in the above example, checkstyle.config.xml resides in the root of the checkstyle-config JAR.

Execute Maven plugin goal on child modules, but not on parent

In a multi-module project, how can you specify that you want to execute a plugin goal in all the child-modules, but not on the parent project? There is <pluginManagement>, but that only defines the configuration for the execution -- the child modules would still need to reference the plugin to get the goal executed:
[...] However, this only configures plugins that are actually referenced within the plugins element in the children. (POM Reference)
Any other way to achieve this?
UPDATE: I've tried this according to Pascal's advice:
<!-- ... -->
<packaging>pom</packaging>
<modules>
<module>child</module>
</modules>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<!-- ... -->
This will still generate a .jar for the parent project, even though the jar goal is bound to the integration-test phase.
According to the Default Lifecycle Bindings, the bindings for a packaging pom are:
Default Lifecycle Bindings - Packaging
pom
package site:attach-descriptor
install install:install
deploy deploy:deploy
So if your parent POM has a <packaging>pom<packaging> (this should be the case as pointed out in a comment) and if you bind your plugins to other phases than those above (see the Lifecycle Reference for a comprehensive list), they won't be executed during the build of the parent POM.
(EDIT: My initial answer is just wrong. If you bind a plugin goal to a particular phase, it will be triggered during that phase, regardless of the packaging of the project. The Default Lifecycle Bindings don't have anything to do with that, they are just default lifecycle bindings. All what matters is if the phase to which the plugin is bound is part of the build lifecyle.)
As you pointed out, you can use the pluginManagement in the parent pom for the configuration of the plugin but if you really want to execute a plugin goal in children modules and not in the parent (you might have good reasons to do this but most of time, plugins won't have much effet on a module with a pom packaging that doesn't have any content), you'll have to reference plugins in the plugins element in the children.
Applied to your example, the parent pom.xml could define the following specifications:
<project>
<packaging>pom</packaging>
...
<modules>
<module>child</module>
</modules>
...
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<id>my-execution-id</id>
<phase>integration-test</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
</pluginManagement>
</build>
...
</project>
And in every child pom.xml, only the following is required:
<project>
...
<build>
...
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
</plugin>
</plugins>
...
</build>
</project>
The described solution with plugin management is certainly correct, but in certain cases it does not fit. Suppose you would like to run several jar:jar goals in the child module each configured with its own settings (configuration) per execution. Or in general, when you don't want to force child poms to explicitly trigger the plugin(s).
In this case the solution that worked for me was to define the executions in the parent pom under a specific profile, and have it activated only in child poms for example by checking for existence of some file or property:
<profile>
<id>generate-dc</id>
<activation>
<file>
<exists>src/main/assembly/some.xml</exists>
</file>
</activation>
Then plugins won't be executed in the parent, but will be executed in all children if those contain the file, or set some property.
I had a similar requirement to run some plugins in the child but not the parent POM. i achieved this by stating <skip>true</skip> in the parent POM.
The parent pom entry is below:
<plugin>
<groupId>eviware</groupId>
<artifactId>maven-soapui-plugin</artifactId>
<version>4.0.0</version>
<inherited>false</inherited>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
</dependency>
</dependencies>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
The child project pom entry is below
<plugins>
<plugin>
<groupId>eviware</groupId>
<artifactId>maven-soapui-plugin</artifactId>
<version>4.0.0</version>
<configuration>
<settingsFile>site-service-web/src/test/soapui/soapui-settings.xml</settingsFile>
<projectFile>site-service-web/src/test/soapui/PodifiSite-soapui-project.xml</projectFile>
<outputFolder>site-service-web/target/surefire-reports</outputFolder>
<junitReport>true</junitReport>
<exportwAll>true</exportwAll>
<printReport>true</printReport>
</configuration>
</plugin>
</plugins>
This below config worked for me. Add the plugin in both the parent and child pom.
Parent :
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<inherited>true</inherited>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
Child
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<inherited>false</inherited>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<skip>false</skip>
</configuration>
</plugin>
</plugins>
</build>
I tried the answer from Pascal but it did not work for me. The plugins referenced in the child pom did not execute, I'm assuming because they did not have a build phase binding.
The post here describes a solution that works by binding the plugins to execution ids and build phases: How to override default binding to phase of a Maven plugin
I'd recommend that to anyone else trying to get this working.
Use <inherited>false</inherited> under the plugins section in the parent project.
Plese refer to this page for more information.

Categories