How to activate a Maven profile per pom.xml? - maven

I have a large Maven project with one master module and lots of children, organized in a nice tree structure. However, some of the modules need special settings which would cause misbehaviour in other modules. For example, there are modules which do stuff on Hadoop which need a Java source level of 1.7, all other Java modules use a source level of 1.8, and now Scala modules are introduced into this tree which compile with scala-maven-plugin which needs special settings for maven-compiler-plugin when compiling mixed Java/Scala modules.
In the past I simply had a master module for the Hadoop stuff which defined the source level of 1.7 and added all necessary Hadoop dependencies. Now I want to avoid defining another master module for Hadoop stuff written in Scala, and yet another module for Non-Hadoop stuff in Scala. I thought I could use profiles, so I defined two profiles in my master POM:
java activates the maven-javadoc-plugin
scala does not activate maven-javadoc-plugin but the maven-scala-plugin and configures it like in the example from its documentation
In the master POM, the java profile is set as active by default, as Java is the default. When a project uses Scala, I want to activate the scala profile, and deactivate java, but setting activeByDefault to false for the java profile has no effect, causing compile errors.
So, is there a way to enable a profile specific to a module without having to set it manually in each pom?

As far as I understood you want to activate profile from child pom based on its configuration. I'm afraid it is not possible. However you can reorganize project tree structure to take advantage of pom inheritance:
pom.xml // general properties for all projects
|-- java-modules
| -- pom.xml // inherits from master pom, configures maven-compile-plugin
| -- java-8-modules
| -- pom.xml // inherits from java-modules pom, uses java 8 compiler
| -- java-8-project-a
| -- java-7-modules
| -- pom.xml // inherits from java-modules pom, uses java 7 compiler
| -- java-7-project-a
|-- scala-modules
-- pom.xml // inherits from master pom, configures maven-scala-plugin
-- scala-project-a
You write one master pom for all modules in top directory, child poms just specify java/scala details.
More about pom inheritance https://maven.apache.org/guides/introduction/introduction-to-the-pom.html#Project_Inheritance

If you want to configure maven profile for each project(module) then you have to add profile setting in the project(module) pom.xml file
<profiles>
<profile>
<activation>
<jdk>1.4</jdk>
</activation>
<your properties goes here>
</profile>
</profiles>
Also if you do not want to execute some profile then you have to add
mvn groupId:artifactId:goal -P !profile-1,!profile-2
in the project pom.xml file

Don't use profile, Mateusz Balbus answer, that is define nested pom-packaged project that define java and scala modules respectively

Related

Intellij Spring maven install error "package does not exist"

Intellij version : Community 2019.2.3
Maven : 3.6.2
Spring : 2.2.0
I am trying to create a very simple Spring maven project with two sub-modules (one independent and another one dependent on independent one).
Root module - testmultimodule
Independent module - independent
Dependent module - dependent
testmultimodule pom.xml has all Spring related declaration and module definition
<modules>
<module>independent</module>
<module>dependant</module>
</modules>
Independent poom.xml is simplest and . only has parent maven declaration
<parent>
<artifactId>testmultimodule</artifactId>
<groupId>in.org.app</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
dependent module pom.xml has the dependency declaration as below to independent module
<dependencies>
<dependency>
<groupId>in.org.app</groupId>
<artifactId>independent</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
I have created a Test class under dependent module and using a User object from independent module. Initially, without the above dependency declaration, asa usual there was compilcation error.
As soon as I add the dependency and builld the project within Intellij IDE with the option "Build Prooject" option from "Build" menu, it successfully builds.
However, if I try to use Maven install option within Intellij right side window option. It always fails stating Error:(3,33) java: package in.org.app.independent.bo does not exist .
I am providing the GitHub URL for the test project , if you want to take a look and test by yourself.
GIT URL:
https://github.com/DhruboB/testmultimodule
I have tried all sort of tweaking found in internet so far e.g.
clearing Intellij Cache & restarting, mvn -U clean install, mvn scope verification, proxy etc.
Any further idea to resolve this? I need to solve this in the Community version of Intellij.
Your parent project includes the definition for the spring-boot-maven-plugin. This leads to each project defining this as a parent to be repacked to an executable JAR by this plugin. This repackaged JAR isn't useable as a dependency in another project.
Either you need to change the configuration of the spring-boot-maven-plugin for the project you want to use as a dependency. This is explained here in the Spring Boot Reference Guide. You now basically have 2 jars from this project, one plain and one executable.
If you don't need that project to be an executable JAR file then just move the spring-boot-maven-plugin to the project that needs to be. All other projects will no be basic JAR files again.
See also How to add a dependency to a Spring Boot Jar in another project?

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.

Custom pom.xml filename in Maven multimodule for Tycho

I have a project with a couple of dozen Eclipse plugins, all inter-related and living in different subfolders. The build was converted to a multi-module manifest-first Tycho build a couple of years ago and it works quite well.
One of the plugins is rather key, and can also be built as a standalone Java app, which doesn't use an Eclipse runtime. Currently it has its own POM file (pom-standalone.xml) so that Jenkins can build the standalone app separately and the Tycho build knows nothing about it - the pom-standalone just lists the previously-built plugin jars (thanks Tycho!) and Eclipse libraries that it needs as dependencies. Couple problems with this approach though:
I cannot easily use IntelliJ to work on the standalone project with Maven dependency management, because it doesn't recognize the custom pom-standalone.xml filename as a POM.
The many jars that this project relies on are checked in to the project for the sake of Tycho and the Eclipse Manifest file, but they're also managed by Maven for the standalone build. So any dependencies have to be added to the pom-standalone.xml file AND entered into the OSGi manifest AND checked in to the source control for Eclipse purposes.
It seems like a straightforward workaround would be to tell Tycho/modules to use something other than pom.xml for the submodule's POM, or perhaps all the multimodule POM files, since Eclipse doesn't use those anyway - then the pom-standalone.xml can be converted to pom.xml and then IntelliJ will be fine with it.
I know you can specify the -f attribute to Maven builds, but will that really apply to all submodules? Can you specify the POM filename for just ONE submodule?
Are there alternative solutions? Eclipse/Tycho/p2 builds seem somewhat of a headache requiring manual library management and checking in libraries to source control, but maybe there have been changes I'm not aware of in the Eclipse build world the last few years.
Found a Similar Question that didn't help much.
You can include projects in an aggregator POM by specifying the full name to the POM file with custom name. Example:
<modules>
<module>org.example.bundle1</module>
<module>org.example.bundle2</module>
<module>org.example.keybundle/pom-tycho.xml</module>
</modules>
This both works in a pure Maven and Maven/Tycho build.
To extend #oberlies answer a little bit:
SCENARIO: top aggregation POM comes in multiple flavors, so any style can be built from the top.
<!-- in file pom.xml -->
<modules>
<module>org.example.bundle1</module>
<module>org.example.bundle2</module>
<module>org.example.keybundle</module>
</modules>
All submodules will be built using their standard pom.xml
and
<!-- in file pom-tycho.xml -->
<modules>
<module>org.example.bundle1/pom.xml</module>
<module>org.example.bundle2/pom.xml</module>
<module>org.example.keybundle/pom-tycho.xml</module>
</modules>
Submodules will be built using the specifically named POM file.
and, likewise:
<!-- in file pom-special.xml -->
<modules>
<module>org.example.bundle1/pom.xml</module>
<module>org.example.bundle2/pom-special.xml</module>
<module>org.example.keybundle/pom-tycho.xml</module>
</modules>
Submodules that have custom POM files use them, and others state they still want the normal POM file, all independent of the name of the top aggregation POM file.
Because mvn -f pom-tycho.xml assumes that file name in all submodules. So if you do want pom.xml in any submodule when the top file isn't named pom.xml you need to fully specify for each submodule.

Inherit build plugin/extension/... in Maven

Say a Maven project has a cool build plugin configured:
<project>
...
<build>
... extensions etc.
</build>
...
</project>
I want this configuration to be reusable, so that I can run the goals provided by the plugins/extensions in any new project. The above project might exist just so that other projects can reuse the config.
What is the best way to achieve this?
Use a parent.pom. Deploy this pom to your local repository. Of course you could configure parent.poms for each type of project that you regularly develop in your organisation. Probably a master.pom with general values (location of servers, organisation name, general code style...) is a good idea. The project specific poms would use this as parent.
Declare this pom.xml as of type pom:
<type>pom</type>
and declare it as a parent in every "child" pom.xml that needs the configured plugins: http://maven.apache.org/guides/introduction/introduction-to-the-pom.html#Project_Inheritance

How to activate a Maven Profile for a specific module in a mutli-module project

We have a multi-module Maven project consisting of a parent POM and 5 or more modules.
Each module can be deployed to a running server as part of the build if we activate our custom "auto-deploy" profile, which is defined explicitly in each module because how/what gets deployed is a little different for each of the modules.
When building from the parent POM though, if I activate the "auto-deploy" profile, Maven will end up deploying all modules, which is almost never what we need to do (based on our dev process etc). But we do want to build from the root as there can be changes across multiple modules and there are dependencies between some modules.
Is there a way, when building from the parent POM, to activate our custom "auto-deploy" Profile for just one of the Modules, but not all of them?
Thanks
If each of your modules will have it's own "auto-deploy" profile, and profile activation will be triggered by variables passed to mvn command, you will be able to run single mvn command on parent module and decide which modules should be deployed simply by declaring activation variables
<profiles>
<profile>
<id>profileId</id>
<activation>
<property>
<name>profileIdEnabled</name>
<value>true</value>
</property>
</activation>
<properties></properties>
</profile>
</profiles>
and then
mvn -DprofileIdEnabled=true
Check out Maven: The Complete Reference - Section 6.2. Using Advanced Reactor Options.
Starting with the Maven 2.1 release, there are new Maven command line options which allow you to manipulate the way that Maven will build multimodule projects. These new options are:
-rf, --resume-from
Resume reactor from specified project
-pl, --projects
Build specified reactor projects instead of all projects
-am, --also-make
If project list is specified, also build projects required by the list
-amd, --also-make-dependents
If project list is specified, also build projects that depend on projects on the list
To build only module-b from the root directory:
$ mvn --projects module-b install

Resources