Maven Inherit Parent profile property as classifier in child - maven

I have multi hierarchy pom maven project.
Parent POM: This contains two profiles with different dependencies and property value (env-type) which is used for classifiers.
deploy_mav/pom_multi_cloud.xml ::
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.abc</groupId>
<artifactId>master-pom-multi-cloud</artifactId>
<version>ver-1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Master POM Multi Cloud</name>
<modules>
<module>pom_multi_cloud_webapp_servlet3.xml</module>
</modules>
<build>
<finalName>${project.artifactId}-${project.version}</finalName>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>default-jar</id>
<configuration>
<classifier>${env-type}</classifier>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.4</version>
<configuration>
<classifier>${env-type}</classifier>
</configuration>
<executions>
<execution>
<id>default-install</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<configuration>
<classifier>${env-type}</classifier>
</configuration>
<executions>
<execution>
<id>default-jar</id>
<configuration>
<classifier>${env-type}</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<profiles>
<profile>
<id>build_aws</id>
<properties>
<env-type>aws</env-type>
</properties>
<dependencies>
<dependency>
<groupId> com.abc.org</groupId>
<artifactId>aws-common</artifactId>
<version>${env-type-common-version}</version>
</dependency>
</dependencies>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
<profile>
<id>build_gcp</id>
<properties>
<env-type>gcp</env-type>
</properties>
<dependencies>
<dependency>
<groupId> com.abc.org</groupId>
<artifactId>gcp-common</artifactId>
<version>${env-type-common-version}</version>
</dependency>
</dependencies>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
</profiles>
</project>
In 1st Level Child pom.xml,
<project>
<groupId>com.abc.org.plat</groupId>
<artifactId>apps-service-ser</artifactId>
<version>ver-1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<parent>
<groupId>com.abc.org</groupId>
<artifactId>master-pom-multi-cloud</artifactId>
<version>ver-1.0.0-SNAPSHOT</version>
<relativePath>../deploy_mav/pom_multi_cloud.xml</relativePath>
</parent>
<modules>
<module>app-ui-service-ingest</module>
<module>shared-service-api</module>
<module>shared-service-engine</module>
<module>shared-service-plan</module>
<module>shared-service-specs</module>
</modules>
</project>
In 2nd level child module shared-service-engine,
<project>
<modelVersion>4.0.0</modelVersion>
<groupId> com.abc.org</groupId>
<artifactId>service-engine</artifactId>
<version>ver-1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Service Engine</name>
<parent>
<groupId>com.abc.org.plat</groupId>
<artifactId>apps-service-ser</artifactId>
<version>ver-1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
...
<dependency>
<groupId> com.abc.org</groupId>
<artifactId>service-plan</artifactId>
<classifier>${env-type}</classifier>
<version>ver-1.0.0-SNAPSHOT</version>
</dependency>
...
</project>
In 3rd level service-plan,
<project>
<modelVersion>4.0.0</modelVersion>
<groupId> com.abc.org</groupId>
<artifactId>service-plan</artifactId>
<version>ver-1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Service Plan</name>
<parent>
<groupId>com.abc.org.plat</groupId>
<artifactId>apps-service-ser</artifactId>
<version>ver-1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependency>
<groupId> com.abc.org</groupId>
<artifactId>service-api</artifactId>
<classifier>${env-type}</classifier>
<version>ver-1.0.0-SNAPSHOT</version>
</dependency>
</project>
Issue is the vaue for env-type ise received till 2nd level.
2nd level has dependency call to 3rd level to which the 2nd level has to pass the classifier value set by the active profile.
The value is not passed to 3rd level and instead dependency searches for -${env-type}.jar
On debuging, getting logs like
[DEBUG] com.abc.org:service-plan:jar:gcp:ver-1.0.0-SNAPSHOT:compile
[DEBUG] org.jooq:jooq:jar:3.11.9:compile (version managed from 3.11.9)
[DEBUG] javax.xml.bind:jaxb-api:jar:2.2.12:compile
[DEBUG] com.abc.org:service-api:jar:${env-type}:ver-1.0.0-SNAPSHOT:compile
[ERROR] Failed to execute goal on project service-engine: Could not resolve dependencies for project com.abc.org:service-engine:jar:ver-1.0.0-SNAPSHOT: Could not find artifact com.abc.org:dashboard
-query-api:jar:${env-type}:ver-1.0.0-SNAPSHOT in nexus (https://repo.abc.xyz/nexus/content/groups/public) -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal on project service-engine: Could not resolve dependencies for project com.abc.org:service-engine:jar:ver-1.0.0-SNAPSHOT: Coul
d not find artifact com.abc.org:service-api:jar:${env-type}:ver-1.0.0-SNAPSHOT in nexus (https://repo.abc.xyz/nexus/content/groups/public)
Caused by: org.apache.maven.project.DependencyResolutionException: Could not resolve dependencies for project com.abc.org:service-engine:jar:ver-1.0.0-SNAPSHOT: Could not find artifact com.abc.org:dashboar
d-query-api:jar:${env-type}:ver-1.0.0-SNAPSHOT in nexus (https://repo.abc.xyz/nexus/content/groups/public)

Solved it by creating a profile in the child project pom.xml and activating it with command line argument value.
mvn -DskipTests -X -P build_aws -Denv-type=aws clean install
<profiles>
<profile>
<id>build_local_aws</id>
<properties>
<test-cloud-type>aws</test-cloud-type>
<cache-version>trunk-2.0.0-SNAPSHOT</cache-version>
</properties>
<activation>
<property>
<name>env-type</name>
<value>aws</value>
</property>
</activation>
</profile>
<profile>
<id>build_local_gcp</id>
<properties>
<test-cloud-type>gcp</test-cloud-type>
<cache-version>trunk-2.0.0-SNAPSHOT</cache-version>
</properties>
<activation>
<property>
<name>env-type</name>
<value>gcp</value>
</property>
</activation>
</profile>
</profiles>

Related

How to run maven from the project

I am trying to start the maven from the root folder (where the file pom.xml is located) of the project via the command line, but I get an error that the command "mvn install" was not found. If I run a maven through the directory where it is installed, then it cannot find the project. How to run maven from the project?
pom.xml
http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
<groupId>ru.evgeniyosipov.facshop</groupId>
<artifactId>facshop</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<name>facshop</name>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.exec.plugin.version>1.4.0</maven.exec.plugin.version>
<integration.container.id>glassfish4x</integration.container.id>
<glassfish.home>${glassfish.home.prefix}/glassfish4</glassfish.home>
</properties>
<profiles>
<profile>
<id>windows</id>
<activation>
<os>
<family>windows</family>
</os>
</activation>
<properties>
<glassfish.home.prefix>c:/</glassfish.home.prefix>
<glassfish.executables.suffix>.bat</glassfish.executables.suffix>
</properties>
</profile>
<profile>
<id>unix</id>
<activation>
<os>
<family>unix</family>
</os>
</activation>
<properties>
<glassfish.home.prefix>${user.home}</glassfish.home.prefix>
<glassfish.executables.suffix />
</properties>
</profile>
</profiles>
<modules>
<module>facshop-events</module>
<module>facshop-entities</module>
<module>facshop-resources</module>
<module>facshop-payment</module>
<module>facshop-store</module>
<module>facshop-shipment</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.4.14</version>
<executions>
<execution>
<id>Deploy</id>
<phase>integration-test</phase>
<goals>
<goal>redeploy</goal>
</goals>
<configuration>
<container>
<containerId>${integration.container.id}</containerId>
<type>installed</type>
<home>${glassfish.home}</home>
</container>
<configuration>
<type>existing</type>
<home>${glassfish.home}/glassfish/domains</home>
<properties>
<cargo.glassfish.domain.name>domain1</cargo.glassfish.domain.name>
<cargo.glassfish.admin.port>4848</cargo.glassfish.admin.port>
<cargo.remote.username>admin</cargo.remote.username>
<cargo.remote.password></cargo.remote.password>
</properties>
</configuration>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
You need to add the maven bin directory to the PATH. Then you can call it from the project directory.

Maven - 'override' not work in external settings

I am using spring boot in my app like this:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
In my external settings.xml I defined resource plugin like this:
<profile>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<id>dev</id>
...
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<configuration combine.self="override">
<delimiters>
<delimiter>^^</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>
</plugins>
</build>
and this not work. When I move it to my pom it works. I know that settings file is red because dev properties are taken from it. What is wrong?

Maven module order changes on the same profile

I have project which has 3 pom files, and 2 maven profiles :prod and dev. The problems is that when I run my dev profile with cmd
mvn clean install -Pdev
it builds project with order :
backend,
frontend
When I build project with prod profile, it builds project with order :
frontend
backend
Which is the way i want. But when I run cmd
mvn clean install
It needs to build project with dev profile, and it does it but in this order : 1.frontend, 2.backend.
and this is the problem, it changes module order. Here is the main pom.xml
<groupId>com.main</groupId>
<artifactId>Main</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Main</name>
<description>Main Parent Project</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<modules>
<module>backend</module>
<module>frontend</module>
</modules>
here is backend pom.xml
<artifactId>backend</artifactId>
<name>backend</name>
<description>Backend Project</description>
<parent>
<groupId>com.main</groupId>
<artifactId>Main</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
...
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
<profiles>${spring-profiles}</profiles>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<build.profile.id>dev</build.profile.id>
<profileActive>dev</profileActive>
</properties>
</profile>
<profile>
<id>prod</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<build.profile.id>prod</build.profile.id>
<profileActive>prod</profileActive>
</properties>
<dependencies>
<dependency>
<groupId>com.main</groupId>
<artifactId>frontend</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</profile>
</profiles>
and here is frontend pom.xml
<artifactId>frontend</artifactId>
<name>frontend</name>
<description>Frontend Project</description>
<parent>
<groupId>com.main</groupId>
<artifactId>Main</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.0</version>
<configuration>
<workingDirectory>src/main/webapp</workingDirectory>
<nodeVersion>v6.0.0</nodeVersion>
<npmVersion>2.7.1</npmVersion>
<nodeDownloadRoot>https://nodejs.org/dist/</nodeDownloadRoot>
<npmDownloadRoot>https://registry.npmjs.org/npm/-/</npmDownloadRoot>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<phase>generate-resources</phase>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>npm rebuild node-sass</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>rebuild node-sass</arguments>
</configuration>
</execution>
<execution>
<id>bower install</id>
<goals>
<goal>bower</goal>
</goals>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>gulp</id>
<goals>
<goal>gulp</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<arguments>${gulpProfile}</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<build.profile.id>dev</build.profile.id>
<profileActive>dev</profileActive>
<gulpProfile>-d</gulpProfile>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<build.profile.id>prod</build.profile.id>
<profileActive>prod</profileActive>
<gulpProfile>-p</gulpProfile>
</properties>
</profile>
</profiles>
Can you help me and tell why is this happening?
Normally this kind of thing is resolved because your frontend would be dependent upon the jar produced by your backend.
So, even if it does not have a compile time dependency you can still add one at provided scope:
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>backend</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
This will tell the maven reactor that it must always build the backend first, without changing the resulting artifact that is built.
First remove <activation> tag from backend/pom.xml. I hoping that you need keep only one profile active at a time by default and which should be dev
Remove the dependency mentioned in backend/pom.xml from prod profile. Your fronend project should be depend on backend.
Add the backend dependency in frontend/pom.xml as below (not in any specific profile)
Code:
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>backend</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
Now try below commands
mvn clean // (default profile `dev`)
mvn clean --activate-profiles prod // (with override profile `prod`)

How to read values from .properties using maven plugin

How to read the properties from .properties file by using maven provided plugin, for one of my current project, I always used to set the properties in the <properties> tag of pom.xml, But here my requirement is, I will set the all properties in some .properties file for ex: dev.properties. It is having the following content inside it.
spring.package=org.springframework
spring.artifact=spring-core
spring.version=3.0.5.RELEASE
So, now I want to set the above properties into the pom.xml like the following:
<dependencies>
<dependency>
<groupId>spring.package</groupId>
<artifactId>spring.artifact</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
I gone through this link : How to read an external properties file in Maven
But it is giving the following error : Missing artifact org.springframework:spring-core:jar:spring.version
Here is the pom.xml
<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>
<groupId>com.ram</groupId>
<artifactId>DynamicProperties</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<spring.version>spring.version</spring.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<urls>
<url>file:///D:/Hadoop_Apps/DynamicProperties/src/main/resources/dev.properties</url>
</urls>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</project>
But spring-core-3.0.5.RELEASE jar is avail in maven repository.
Is there any other plugin in maven to do the same, or did I missed any additional config here.
Please correct if I am wrong.
Thanks.
First of all, when Maven reads your pom.xml, it'll immediately replace placeholders such as ${spring.version} with the actual value you specify as
<properties>
<spring.version>spring.version</spring.version>
</properties>
So changing the values later via a plugin is too late! Maven will not do this, however, if there's no value available at this time. Therefore you can remove these properties from pom.xml and let Maven plugin define them later in build lifecycle. This usually solves uses of properties overridden by plugins, but...
Second, there might be still another problem: Maven will likely resolve dependencies (including their versions) before even executing any plugin, which will prevent you from doing this whole thing. If that's the case, you can move your properties to a profile and activate a certain profile instead.
<properties>
<!-- default goes here, when no profile is used -->
<spring.version>3.0.4-RELEASE</spring.version>
</properties>
<profiles>
<profile>
<id>dev</id>
<properties>
<spring.version>3.0.5-RELEASE</spring.version>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<spring.version>3.0.1-RELEASE</spring.version>
</properties>
</profile>
</profiles>
Please find below the corrected pom.
<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>
<groupId>com.ram</groupId>
<artifactId>DynamicProperties</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<spring-version>spring.version</spring-version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<urls>
<url>file:///${basedir}\src\main\resources\config.properties</url>
</urls>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
The problem was in -
<spring.version>spring.version</spring.version>
tag. It should have been
<spring-version>spring.version</spring-version>
inside properties tag.
BR

In maven - how to rename the output .war file based on the name of the profile in use

I have three profiles in my pom.xml for our application...
dev (for use on a developer's)
qa (for use on our internal qa server)
prod (production).
When we run our maven build all three profiles ouput a war file with the same name. I would like to output $profilename-somearbitraryname.war
Any ideas?
You've answered yourself correctly:
<profiles>
<profile>
<id>dev</id>
<properties>
<rp.build.warname>dev</rp.build.warname>
</properties>
</profile>
<profile>
<id>qa</id>
<properties>
<rp.build.warname>qa</rp.build.warname>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<rp.build.warname>prod</rp.build.warname>
</properties>
</profile>
</profiles>
but there is a simpler way to redefine WAR name:
<build>
<finalName>${rp.build.warname}-somearbitraryname</finalName>
<!-- ... -->
</build>
No maven-war-plugin is needed.
The answer was simple...
Define a property in each profile like this...
<profile>
<id>qa</id>
<properties>
<rp.build.warname>ourapp-qa</rp.build.warname>
</properties>
</profile>
Then add this to your plugins...
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<packagingExcludes>WEB-INF/web.xml</packagingExcludes>
<warName>${rp.build.warname}</warName>
</configuration>
</plugin>
In maven you must use <bundleFileName> in the <module>
You should follow this link to ensure your modules are rewritted:
http://maven.apache.org/plugins/maven-ear-plugin/examples/customizing-a-module-filename.html
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.10.1</version>
<configuration>
[...]
<modules>
<ejbModule>
<groupId>artifactGroupId</groupId>
<artifactId>artifactId</artifactId>
<bundleFileName>anotherName-1.2.3.jar</bundleFileName>
</ejbModule>
</modules>
</configuration>
</plugin>
</plugins>
</build>

Resources