maven configuring for alpha, beta, prod builds - maven

my project will have different resources for alpha, beta, and prod builds. i use a python script to build and deploy and want to simply pass a variable to the build to say what version we are building.
like this
mvn package -DbuildMode=beta
i would like to have my resources set up like this
java/main/resources
java/main/resources-alpha
java/main/resources-beta
java/main/resources-prod
so if i send the beta variable, maven will use
java/main/resources
java/main/resources-beta
when its building the war file.
how would i begin configuring this in my pom file? im running maven 3.0.3

You should use maven profiles.
They can be activated either directly from the command line, or by checking for some environment artifact ( property, file, etc. ).
Here is the article -> http://maven.apache.org/guides/introduction/introduction-to-profiles.html
In this example it uses property activation
<profile>
<id>beta</id>
<activation>
<property>
<name>buildMode</name>
<value>beta</value>
</property>
</activation>
<build>
<resources>
<resource>
...
<directory>${basedir}/src/main/resources-beta</directory>
...
</resource>
</resources>
</build>
</profile>

Related

Skip compilation in gmavenplus plugin

I currently work in big project built by Maven which has many integration tests modules which are marked as main (not testing) sources.
I am trying to create a profile which would skip compilation of these modules.
I expected gmaven plugin to allow "skip" configuration parameter but this is not the case.
Is there any way to skip module processing without pointing gmaven plugin to non-existent directory and without copy-paste of all modules except integration tests to a separate profile?
You can put the integration test modules in a separate profile of the parent pom where you list the modules. The profile should be active unless you disable it by setting a property when running the Maven build (-DskipIntegrationTestModules). (Don't use activeByDefault.)
<modules>
<module>my-project</module>
</modules>
<profiles>
<profile>
<id>build-integration-tests</id>
<activation>
<property>
<name>!skipIntegrationTestModules</name>
</property>
</activation>
<modules>
<module>my-project-integration-test</module>
</modules>
</profile>
</profiles>
You can find more details in the Maven Introduction to Build Profiles.
You should also know that it can be dangerous to have modules in build profiles because they could be accidentally left out when doing release builds. I think it should be OK in this case because the profile has to be deactivated explicitly.

What is the difference between mvn clean install -Drelease-build and mvn clean install?

I need to know what is the difference between these two commands which do almost same thing if we execute this command.
Maven doesn't assign any special meaning to release-build. However, projects can use properties (-Dproperty-name=value or just -Dproperty-name) to activate profiles that change the way the project is built (Maven - activate profile based on project property). It's likely to enable some extra steps that are only necessary for final releases. For example, this project uses it to include a native library in the build:
<profile>
<id>native</id>
<activation>
<property>
<name>release-build</name>
</property>
</activation>
<modules>
<module>pi4j-native</module>
</modules>
</profile>
There's no general answer: you'll need to consult the documentation, or build, of the project you're working with.
You can do this much more simpler automatically to activate a profile in case of a release simply via the maven-release-plugin which already supports that out-of-the-box like this:
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.4.2</version>
<configuration>
<releaseProfiles>release</releaseProfiles>
</configuration>
</plugin>
Apart from that it's really bad to acitvate a module only in case of a profile is active. This will lead so several problem.

Using the properties tag within maven profiles

I am in reference to "Maven: The Complete Reference" and especially the section regarding profiles which documents the use of a <properties... tag within the <profile... tag here: see here
<profile>
<id>development</id>
<activation>
<activeByDefault>true</activeByDefault>
<property>
<name>environment.type</name>
<value>dev</value>
</property>
</activation>
<properties>
<database.driverClassName>com.mysql.jdbc.Driver</database.driverClassName>
<database.url>
jdbc:mysql://localhost:3306/app_dev
</database.url>
<database.user>development_user</database.user>
<database.password>development_password</database.password>
</properties>
</profile>
What I am not sure about is what happens when the mvn install -Denvironment.type=dev command is run:
Will this create a .properties file?
If not how and where will tomcat (for instance) read the individual properties when the app is tested in dev?
Will this create a .properties file?
No, it won't. This would set the properties used by maven. This is, with mvn install -Denvironment.type=development maven would use the value 'development_user' for the variable 'database.user' (that you can use as ${database.user} in poms and filtered resources).
If not how and where will tomcat (for instance) read the individual properties when the app is tested in dev?
The thing is to tell maven to filter (and modify) the resources that you want to customize depending on the profile (properties.files).
So, first you have to say maven to filter the resources:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
Then modify your properties files to use maven variables. For example, your db properties file would look like this:
database.driverClassName=${database.driverClassName}
database.url=${database.url}
#...

Enable certain Maven tests by passing a command line switch

I have a single module project that has some unit tests that require an external hardware device. I don't want these tests to execute unless I indicate that the device is available.
I feel like this is solvable using Maven properties and the SureFire exclusion/inclusion configuration, but I can't quite see how to do it. A similar question shows how to disable/enable all the tests in a project based on a Maven property, but doesn't quite answer my issue.
In summary, I wish to identify a pattern (e.g. **/*ResourceTest.java) that describes the tests I don't want to run, unless I pass a Maven property to enable them.
E.g.
mvn clean install (runs the standard tests, but skips device-related tests)
mvn -Drun.device.tests=true clean install (runs all the tests)
Thanks in advance.
(Edited to remove the misleading usage of the word "resource" > replaced with "hardware device").
You also can just use the JUnit Assume methods to decide (inside the test) if a test should be executed or skipped.
The best option IMHO would however be to 'declare' the device dependend tests to be "integration tests" and let them be executed by the Maven Failsafe Plugin. I think this would be the "build in" maven solution without any profile 'magic'.
The link you provided gave the good answer.
The right way
Use a mix of Profile Management and Surefire Configuration inclusion / exlcusion is the right way.
You should ask yourself WHY you want to activate some tests dependings on a resource. The resource should always been in your classpath.
If not, you probably just want to activate some test manually, for some tricky reasons. In that case consider this is a bad use of Maven (how would you automate that on a distant server for instance ?)
What you asked
If you really really want to do that, because you have some good reasons that we are not aware of, simply use this :
This example will trigger the profile when the generated file target/generated-sources/axistools/wsdl2java/org/apache/maven is missing.
Example from Maven official doc : http://maven.apache.org/guides/introduction/introduction-to-profiles.html
<profiles>
<profile>
<activation>
<file>
<missing>target/generated-sources/axistools/wsdl2java/org/apache/maven</missing>
</file>
</activation>
...
</profile>
</profiles>
As of Maven 2.0.9, the tags and could be interpolated. Supported variables are system properties like ${user.home} and environment variables like ${env.HOME}. Please note that properties and values defined in the POM itself are not available for interpolation here, e.g. the above example activator cannot use ${project.build.directory} but needs to hard-code the path target.
You could find more information here : http://www.sonatype.com/books/mvnref-book/reference/profiles-sect-activation.html
Hope that will help.
Don't hesitate to challenge my point of view with you own reasons (even legacy code ;) ) or experience
To expand on #Jean-Rémy answer, I have done the following in my project POM file:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<excludes>
<exclude>${tests.to.skip}</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<!-- This profile will be used when running tests without a device -->
<id>default-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<tests.to.skip>**/*DeviceTest.java</tests.to.skip>
</properties>
</profile>
<profile>
<id>device-profile</id>
<activation>
<property>
<name>device</name>
<value>true</value>
</property>
</activation>
<properties>
<!-- Unsure how to match nothing -->
<tests.to.skip>NOTHING</tests.to.skip>
</properties>
</profile>
This creates two profiles, the default profile will exclude the device tests, whereas the "device-profile" will execute all tests.
To execute the device profile, one can execute mvn -Ddevice=true test.

Separate Jenkins-Project for deploying to JBoss

I have a Jenkins build which builds a maven project with -PmyProfile clean package. This works fine. Now I want the project be deployable but in a separate task (JBoss deployment) so it can be triggered explicitly via the jenkins GUI. For that, I have the following in my pom:
<profiles>
<profile>
<id>myProfile</id>
<properties>...</properties>
<build>
<plugins>
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<version>7.0.0.Final</version>
<configuration>
<hostname>localhost</hostname>
<port>29999</port>
<username>admin</username>
<password>admin</password>
<filename>${project.build.finalName}.war</filename>
<name>my-webapp</name>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Now I only want to call that single deployment via mvn jboss-as:deploy separately. But how would I do that? If I create a second Jenkins project, everything needs to be built again, so that's pretty stupid. Building as a separate module does not work, either (some error with "building single modules not supported for maven 3").
Any ideas?
Thanks
It sucks a little, but you can always get stuff from another Jenkins workspace by using filesystem relative path like ../../SecondJob/workspace (or use symlink). I used to do this for the same case (deploying as separate job) for all my projects and it works, it's just not elegant, but I believe there's no built-in solution in Jenkins for that.
Alternatively, it seems there's Jenkins plugin for that, but I haven't used it and can't tell anything about it.
Possible trick:
Have only one project, but parameterize it with DEPLOY parameter set to FALSE by default. The build will contain your main build as well as an Invoke top-level Maven targets post-build step for deployment. The deployment step will be invoked only if DEPLOY is TRUE. To do that you use Conditional Build Step plugin.
There is a new deploy-only goal added in version 7.5.Final. You can grab the war from the first job with Copy Artifact Plugin.
References:
https://docs.jboss.org/jbossas/7/plugins/maven/latest/deploy-only-mojo.html
https://github.com/jbossas/jboss-as-maven-plugin/pull/56/commits

Resources