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

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>

Related

Maven Inherit Parent profile property as classifier in child

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>

<activeByDefault/> doesn't work when another profile triggered

I have profiles look like this.
<profile>
<id>active-by-default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>${version.org.mongodb}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</profile>
<profile>
<id>java8</id>
<activation>
<jdk>(,1.8]</jdk>
</activation>
<build>
<plugins>
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<configuration>
<libs>
<lib>${java.home}/lib/rt.jar</lib>
<lib>${java.home}/lib/jce.jar</lib>
<lib>${java.home}/lib/jsse.jar</lib>
</libs>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>java9</id>
<activation>
<jdk>[1.9,)</jdk>
</activation>
<build>
<plugins>
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<configuration>
<libs>
<lib>${java.home}/jmods/java.base.jmod</lib>
</libs>
</configuration>
</plugin>
</plugins>
</build>
</profile>
Those two java- profiles are for ProGuard.
And I found the active-by-default profile doesn't work even with no profiles specified.
I found it works when I remove one of those java- profile which meets my current JDK version.
Is this intended?
Yes, this is the documented behaviour :
This profile will automatically be active for all builds unless another profile in the same POM is activated using one of the previously described methods. All profiles that are active by default are automatically deactivated when a profile in the POM is activated on the command line or through its activation config.
https://maven.apache.org/guides/introduction/introduction-to-profiles.html

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 3 profile with extensions

My question had been addressed in this thread, but the explanation is not clear.
I have this build definition in one of my pom.xml files:
<build>
<finalName>${my.project}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
<extensions>
<extension>
<groupId>org.kuali.maven.wagons</groupId>
<artifactId>maven-s3-wagon</artifactId>
<version>1.1.19</version>
</extension>
</extensions>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/settings.properties</include>
</includes>
</resource>
</resources>
</build>
Notice that I'm using the maven-s3-wagon extension.
Next, I would like to have 2 different profiles, each with it's own settings, plugins and extensions but maven does not allow the extensions tag under a profile.
When I try using a profile:
<profiles>
<profile>
<id>local-build</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<finalName>${my.project}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
<extensions>
<extension>
<groupId>org.kuali.maven.wagons</groupId>
<artifactId>maven-s3-wagon</artifactId>
<version>1.1.19</version>
</extension>
</extensions>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/settings.properties</include>
</includes>
</resource>
</resources>
</build>
</profile>
</profiles>
I get a an error in my pom:
cvc-complex-type.2.4.a: Invalid content was found starting with element 'extensions'. One of '{"http://maven.apache.org/POM/4.0.0":defaultGoal, "http://maven.apache.org/POM/
4.0.0":resources, "http://maven.apache.org/POM/4.0.0":testResources, "http://maven.apache.org/POM/4.0.0":directory, "http://maven.apache.org/POM/4.0.0":filters, "http://
maven.apache.org/POM/4.0.0":pluginManagement}' is expected.
Question So using the extension tag means I can't use profiles? How can I use or change build extensions via profile?
Indeed, the official Maven POM reference is not clear about the possible usage of extensions as part of a Maven profile, since it states you can have a build element within it, but not what of the build section.
However, the official Maven model effectively filters and provides what of the build section you can actually use within a profile section. And indeed extensions is not there.
However, what are Maven extensions? Build/Lifecycle enhancement, but also (and essentially): a library added to the runtime classpath of the Maven build, which participates to the build, but it is not packaged with the final artifact.
Hence, in such a scenario (if you need to have extensions in profile or have a profile to change/add an extension) you could use the following trick:
Have an harmless extension as default extension of your build (where harmless means whatever library which could be part of your build classpath and essentially not affect it at all)
Have properties defining the GAV coordinates (GroupId, ArtifactId, Version) of this extension
Have a profile which overrides these properties with the desired (useful) extension
As an example, given the following sample POM:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample</groupId>
<artifactId>project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<extension.groupId>junit</extension.groupId>
<extension.artifactId>junit</extension.artifactId>
<extension.version>4.11</extension.version>
</properties>
<build>
<extensions>
<extension>
<groupId>${extension.groupId}</groupId>
<artifactId>${extension.artifactId}</artifactId>
<version>${extension.version}</version>
</extension>
</extensions>
</build>
<profiles>
<profile>
<id>customize-extension</id>
<properties>
<extension.groupId>junit</extension.groupId>
<extension.artifactId>junit</extension.artifactId>
<extension.version>4.12</extension.version>
</properties>
</profile>
</profiles>
</project>
The default build (without the customize-extension profile activated), would use the default defined properties and as such add junit as build extension: this is harmless (although it may create conflicts with another junit version of your build, so make sure you use the same version of use an even more harmless library for that).
You can check Maven will pick it up by running a really first build phase, just to check information in our case, and enable the debug flag:
mvn initialize -X
And checking as part of the build log:
[DEBUG] Populating class realm extension>junit:junit:4.11
[DEBUG] Included: junit:junit:jar:4.11
Now let's use our trick: let's add (change) a build extension via profile:
mvn initialize -X -Pcustomize-extension
And as part of our build log we would have:
[DEBUG] Populating class realm extension>junit:junit:4.12
[DEBUG] Included: junit:junit:jar:4.12
Bingo. Maven picked up a different extension (in this case, a different version, the 4.12) and we succeeded on changing (or actually adding a meaningful) build extension via profile.
Just a crazy idea: use modules
Define a parent pom like this:
<groupId>org.example</groupId>
<artifactId>my-parent</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<profiles>
<profile>
<id>use-pom1</id>
<modules>
<module>pom1</module>
</modules>
</profile>
<profile>
<id>use-pom2</id>
<modules>
<module>pom2</module>
</modules>
</profile>
</profiles>
Define the desired extensions on pom1 and pom2.
I think the solution is here http://maven.apache.org/guides/mini/guide-using-extensions.html
Define a build section where extensions are defined and then into the profile set the attribute true ( like in the second profile shown below )
<build>
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>2.9</version>
</extension>
</extensions>
</build>
<profiles>
<profile>
<id>create-default</id>
<activation>
<activeByDefault>true</activeByDefault>
<property>
<name>build</name>
<value>full</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>create-core</id>
<activation>
<property>
<name>build</name>
<value>full</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<extensions>true</extensions>
<version>2.6</version>
<configuration>
<finalName>import-station-core-${project.version}</finalName>
</configuration>
<executions>
<execution>
<id>make-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>

Resources