Define maven profiles outside POM - maven

Is there a way to define my maven profiles outside POM file but not in .m2/settings.xml?
I want to define them in a separate xml file inside the application (way to work efficiently with maven 2 and 3) because I am using maven 2 and intend to switch to 3 soon.

Until Maven 2.2.1 you could define your profiles into the profiles.xml file as a separate file but with Maven 3 this opportunity has been removed. The question ist why do you need a separate file for the profiles?

You may want to go through this maven documentation on build profiles, which describes the types of profiles and how each can be used.
As I see it, profiles cannot be defined outside pom.xml or settings.xml, if you want to use maven 3.

<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<build.profile.id>dev</build.profile.id>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<build.profile.id>prod</build.profile.id>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<build.profile.id>test</build.profile.id>
</properties>
</profile>
</profiles>
And add a filter
<filters>
<filter>src/test/resources/${build.profile.id}/config.properties</filter>
</filters>
And add any directory (dev, prod, test)

I was recently migrating an application to maven3 from maven2. With maven 3 there is no possibility to have external profiles. But what can be done is to have external property files. This can be achieved by maven-properties-plugin
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<!-- Associate the read-project-properties goal with the initialize phase,
to read the properties file. -->
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>../com.tak/build.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
So here I have explained how to do that http://programtalk.com/java/migrate-from-maven2x-to-maven3x/

Related

Spring boot change pom configuration with active profile

I was trying to change configuration of the pom based on the active profile (dev, test, qa, prod). but every time it was calling the default one (prod)
I have given the profile info in VM arguments in intellij
arguments : -Dspring.profiles.active=dev
Decleration (in POM.xml)
<profiles>
<profile>
<id>dev</id>
<properties>
<currentRegion>run build_dev</currentRegion>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<currentRegion>run build_test</currentRegion>
</properties>
</profile>
<profile>
<id>qa</id>
<properties>
<currentRegion>run build_qa</currentRegion>
</properties>
</profile>
<profile>
<id>prod</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<currentRegion>run build_prod</currentRegion>
</properties>
</profile>
</profiles>
Usage(in POM.xml)
<build>
<plugins>
<plugin>
<executions>
<execution>
<configuration>
<arguments>${currentRegion}</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Every time, this is retuning run build_prod (the default one)
Actually i have combined the spring boot and angular for some testing purpose and i want to run the angular on environment with different environment.ts file , when i hardcode the arguments in pom like run build_dev/test it works file , i want to automate it arguments based on the active profile .
Any Suggestions/Solution is highly appreciated.

In maven, how to override plugin configuration in settings.xml

I want to override a particular plugin configuration that's defined in the pom.xml. I don't want to modify the pom.xml for various reasons. Is there a way to define a config attribute for that plugin in settings.xml that override corresponding pom.xml plugin config?
In the below example, you'll notice that the plugin xx-plugin is defined in profile1 in pom.xml. In my settings.xml I've already defined profile2 to override property prop1 from pom.xml. But how to override config3. I apologize if this is a silly question. I am a little new to maven.
This is what my pom.xml looks like:
<profile>
<id>profile1</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>com.xx.yyy</groupId>
<artifactId>xx-plugin</artifactId>
<executions>
<execution>
<id>xx-install</id>
<phase>install</phase>
<goals>
<goal>xx-install</goal>
</goals>
<configuration>
<config1>AAA</config1>
<config2>BBB</config2>
<config3>CCC</config3> <!-- I want to override this with value DDD -->
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
This is what my settings.xml looks like:
<profile>
<id>profile2</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<prop1>overriden-value</prop1> <!-- This works -->
</properties>
<!-- Somehow override config3 here -->
<!-- <config3>DDD</config3> -->
</profile>
AFAIK you can only override properties with settings.xml profiles. You'd have to change your plugin's configuration to use a property instead of a fixed value:
<!-- define your property -->
<properties>
<prop1>CCC</prop1>
</properties>
<profile>
<id>profile1</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>com.xx.yyy</groupId>
<artifactId>xx-plugin</artifactId>
<executions>
<execution>
<id>xx-install</id>
<phase>install</phase>
<goals>
<goal>xx-install</goal>
</goals>
<configuration>
<config1>AAA</config1>
<config2>BBB</config2>
<config3>${prop1}</config3> <!-- I want to override this with value DDD -->
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
Remember that profiles with activeByDefault set to true will get deactivated if any other profile gets activated in your build invocation. See http://maven.apache.org/guides/introduction/introduction-to-profiles.html
If you do not want to change the pom.xml for a plugin you can set the configuration as JVM parameter when running maven as stated in the Generic Configuration chapter of the Maven Guide to Configuring Plugins.
Example:
mvn my-plugin:my-goal -Dplugin.property=ABC
Example for the wildfly plugin (this is where I needed it and did not want to change the pom.xml of a demo project when deploying to a server group in a domain context):
mvn clean install wildfly:deploy -Dwildfly.serverGroups=<server-group-name>
The maven documentation also states that most plugins define help goals to explain users how to configure them.
Exaple for the wildfly plugin:
mvn wildfly:help -Dgoal=deploy -Ddetail

How to configure Clover license location in Maven and Jenkins

I know how to Clover in Maven (in local Eclipse or Jenkins), the problem is it's not a good idea to ask everyone put clover license in the same directory. Is there any suggestion for it?
<properties>
<clover.version>3.1.8</clover.version>
<clover.license>C:\xxx\clover_license</clover.license>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.atlassian.maven.plugins</groupId>
<artifactId>maven-clover2-plugin</artifactId>
<version>${clover.version}</version>
<configuration>
<license>${clover.license}</license>
</configuration>
</plugin>
</plugins>
</build>
I think use Maven parameter to pass the variable is possible, but I need to set it in every project in Jenkins. And if I change the file in Jenkins server, I need to modify every project.
-Dclover.license=C:\xxx\clover_license
See How to configure your clover.license for advice here. I recommend the suggestion to "Set up your .m2/settings.xml file", so you can define that property once:
<profiles>
<profile>
<id>my-clover-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<!-- You can define the path to a license file: -->
<maven.clover.licenseLocation>/path/to/clover.license</maven.clover.licenseLocation>
<!-- Or you can embed license key (remember to keep newline characters): -->
<maven.clover.license><![CDATA[
...
]]></maven.clover.license>
</properties>
</profile>
</profiles>

How to configure maven to use different log4j.properties files in different environments

I want to be able to use different log4j configuration for different environments.
In my development environment, I want to use log4j.properties (A). But when I build in Maven for the production environment, I want to use log4j.properties (B).
Please tell me how to configure this in my pom.xml?
You can use profiles to achieve the desired behavior:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>log4j</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>output_directory</outputDirectory>
<resources>
<resource>${log4j.file}</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<log4j.file>path_to_file_A</log4j.file>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<log4j.file>path_to_file_B</log4j.file>
</properties>
</profile>
</profiles>
1. in your project add 3 folders :
Your Project\src\main\resources\
\A > log4j.properties
\B > log4j.properties
\Default > log4j.properties
2. in pom.xml
<properties>
<param>Default</param>
</properties>
<build>
<resources>
<resource>
<directory>src/main/resources/${param}</directory>
</resource>
</resources>
</build>
3.
- if : mvn clean install : classpath => log4j.properties(Default)
- if : mvn clean install -Dparam=A : classpath => log4j.properties(A)
- if : mvn clean install -Dparam=B : classpath => log4j.properties(B)
> much better than using profiles is more extensible without touching the pom
You don't need the maven-resources-plugin if you have a simple environment.
In this example, log4j.properties B is the file you use for production and is in the directory src/main/java and log4j.properties A is the file you use for development and is in the directory /Users/junger/.m2/.
In your pom.xml:
<properties>
<log4j.properties.directory>src/main/java</log4j.properties.directory>
</properties>
<build>
<resources>
<resource>
<directory>${log4j.properties.directory}</directory>
<includes>
<include>log4j.properties</include>
</includes>
</resource>
</resources>
</build>
Now, in your /Users/junger/.m2/settings.xml (create one if it doesn't exist):
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<log4j.properties.directory>/Users/devuser/.m2/</log4j.properties.directory>
</properties>
</profile>
</profile>
By using this method, each developer can have a different log4j.properties directory and you keep your pom.xml clean.
Simplest way for me,
Define a system variable ENV and set its value _dev for your development env.
Where you refer this file use like this log4j${ENV}.properties
So,
In production it simply use log4j.xml and for your dev log4j_dev.xml
In order to prevent problems it would be better to create also ENV variable for production as _pro so for production log4j_pro.xml, for dev log4j_dev.xml will be used.
I believe that relying on different files than copying resource is better practice.
There is a very simple solution good for small projects with jar packaging (I haven't tested it on war packaged projects). The only disadvantage is that you have to duplicate all resources, but if your only resource is log4j.properties this is not a problem.
If you have a directory tree like this:
...
You should have the following pom:
<build>
<finalName>${project.artifactId}</finalName>
<sourceDirectory>src/</sourceDirectory>
<resources>
<resource>
<directory>${resources.path}</directory>
</resource>
</resources>
</build>
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<resources.path>resources/prod</resources.path>
</properties>
</profile>
<profile>
<id>dev</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<resources.path>resources/dev</resources.path>
</properties>
</profile>
</profiles>
Then when you use dev profile log4j.properties from resources/dev is used. When you use any other profile or no profile at all then log4j.properties from resources/prod is used. So your *.jar should look like this:
Of course if you have different resources location, for example main/java/resources/..., you should specify it instead of resources/...
To some extent you can reference environment variables inside a log4j.properties to add environment dependent behavior.
e.g.
log4j.rootLogger=${rootLoggerLevel}, ${appender}

GlassFish 3 + Maven + remote deploy

I couldn't find any clear answer about how to deploy simple Maven based project to remote GlassFish server via maven like
mvn package xxx:deploy
I think only cargo plugin supports GlassFish 3. Right?
I've problems at configuration side.
Any sample remote GlassFish deployment will be great. Cargo is not a must, if others are support remote GlassFish then we can also use it too.
In case you want to only use maven-glassfish-plugin (let say version 2.1), you can do a remote deploy by specifying the "host" parameter. Below is an example where configurations are setup in maven settings.xml and an plugin loads them using a profile:
In settings.xml define a profile:
<profile>
<id>production-config</id>
<properties>
<glassfish.glassfishDirectory>/var/local/glassfish/</glassfish.glassfishDirectory>
<glassfish.user>admin</glassfish.user>
<glassfish.adminPassword>adminadmin</glassfish.adminPassword>
<glassfish.domain.name>prd-domain</glassfish.domain.name>
<glassfish.domain.host>NAMEOFYOURREMOTEHOST</glassfish.domain.host>
<glassfish.domain.adminPort>10161</glassfish.domain.adminPort>
.
.
</properties>
</profile>
Next put this profile in your active profiles:
<activeProfiles>
<activeProfile>production-config</activeProfile>
</activeProfiles>
In your maven project pom.xml, create a profile and add the maven-glassfish-plugin in your list of profiles:
<profile>
<id>production</id>
<activation>
<activeByDefault>false</activeByDefault>
<os>
<arch>x86</arch>
<family>linux</family>
</os>
<property>
<name>profile</name>
<value>production</value>
</property>
<file>
<exists>
${glassfish.glassfishDirectory}/domains/${glassfish.domain.name}/config/domain.passwords
</exists>
</file>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.glassfish.maven.plugin</groupId>
<artifactId>maven-glassfish-plugin</artifactId>
<configuration>
<terse>true</terse>
<echo>true</echo>
<debug>true</debug>
<glassfishDirectory>${glassfish.glassfishDirectory}</glassfishDirectory>
<user>${glassfish.user}</user>
<adminPassword>${glassfish.adminPassword}</adminPassword>
<domain>
<name>${glassfish.domain.name}</name>
<host>${glassfish.domain.host}</host>
<adminPort>${glassfish.domain.adminPort}</adminPort>
</domain>
<components>
<component>
<name>${project.artifactId}</name>
<artifact>${project.build.directory}/${project.build.finalName}.war</artifact>
</component>
</components>
</configuration>
<executions>
<execution>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
This should do the trick. You can run this profile using maven : mvn glassfish:deploy -P production or just mvn deploy -P production (since we have added the goal deploy inside the executions part of plugin)
Using the model above you can create different profile per environment (dev, acc, tst, prd), and use different settings. For instance you can create a developer profile where a local glassfish is being used to deploy and run unit/integration tests on it.
Common mistake people make is to mix up the settings for the machine from where you are doing the remote deployment with the host where deployment is to be installed. glassfishDirectory is place from where you are running the deployment plugin from. As a result of mistake plugin just hangs, doing nothing and just waiting giving the impression that something is happening. Another mistake is to specify a password file instead of a password for a remote deploy which will also result in nothing.
As far as I know and could find around, only Cargo delivers (or deploys, in this case).
This is an example tested as working on a Maven OSGi WAR project:
<build>
<plugins>
...
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.1.2</version>
<configuration>
<container>
<containerId>glassfish3x</containerId>
<type>remote</type>
</container>
<configuration>
<type>runtime</type>
<properties>
<cargo.hostname>myhostname</cargo.hostname>
<cargo.remote.username>myusername</cargo.remote.username>
<cargo.remote.password>mypassword</cargo.remote.password>
</properties>
</configuration>
</configuration>
<dependencies>
<dependency>
<groupId>org.glassfish.deployment</groupId>
<artifactId>deployment-client</artifactId>
<version>3.2-b06</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
As you can see, the trick lies in the deployment-client dependency.
For the sake of completeness, you then just mvn package cargo:deploy and Bob's your uncle.

Resources