Maven. Build only module that have deploy profile - maven

Context:
I have a rather large system with several maven module formed in a hierarchy. When I need to develop I can go to the root and build using a specific profile -Pdeploy
The problem with this is that, my entire project is built (which takes a while) when I only in truth need to build a dozen lightweight modules that just deploy.
How should I got into improving the team's efficiency when deploying?

Basic Idea: You may not skip building modules but you may skip some of your plugin executions contained.
Usually your repository will already have build module artifacts present, so the overall speed should already be better once a previous build have been run and module artifacts can be pulled from there.
The idea is that you add a profile setting that defines skip-properties according to what you may want to omit when doing a deploy profile build only.
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault />
</activation>
<properties>
<skip.documentation>false</skip.documentation>
<skip.sign>false</skip.sign>
<skip.sources>false</skip.sources>
<skip.checks>false</skip.checks>
<skip.reports>false</skip.reports>
<skip.installer>false</skip.installer>
</properties>
</profile>
<profile>
<id>deploy</id>
<properties>
<skip.documentation>true</skip.documentation>
<skip.sign>true</skip.sign>
<skip.sources>true</skip.sources>
<skip.checks>true</skip.checks>
<skip.reports>true</skip.reports>
<skip.installer>true</skip.installer>
</properties>
</profile>
</profiles>
Your pom than might contain
<plugin>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>${version.maven-checkstyle-plugin}</version>
<configuration>
<skip>${skip.checks}</skip>
</configuration>
</plugin>
This method can be applied on a project pom level (pluginDependencies) or overridden in each module.

Related

In a Maven multi-module project, how can I run a full build and run a specific plugin on one child?

I have a multi-project maven project. One child only has a specific plugin and I want it to be optional (so not bound to a specific phase).
How can I run a full clean install on the entire project and additionally run a project's specific plugin?
I've encountered this post but it looks like an overkill, and it is not so easy in my specific case.
Your best option is to use maven build profiles.
In example, use this snippet in child module:
<profiles>
<profile>
<id>only-in-child-module</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
....
</plugins>
</build>
</profile>
</profiles>
This build profile will not be active unless you explicitly ask maven for it like:
mvn clean install -Ponly-in-child-module

Can a multi-module maven archetype be set up to have optional modules ?

I am going to create a multi-module archetype. It will generate several modules. Some users of the archetype may need all of them, while some only need some of them.
Can my archetype take arguments from the command line and decide which modules to generate? I checked https://maven.apache.org/archetype/archetype-models/archetype-descriptor/archetype-descriptor.html and it doesn't seem to support that.
In this specific case, the archetype could always create all the required modules and move the different flavors (set of modules) into profiles. Only one profile will be active by default as specified during the archetype:generate step.
As such, if I want to have the set of modules for flavorA, I will run the archetype as
mvn archetype:generate -DarchetypeGroupId=.. -DflavorA=true
And the archetype will pass this variable to the activeByDefault element of the flavorA profile re-defining the modules element for the set of modules required by the flavorA users.
The same could be done for flavorB and flavorB (for example), each defining a different set of modules.
An example of such an aggregator/parent POM as part of the archetype would be:
<profiles>
<profile>
<id>flavourA</id>
<activation>
<activeByDefault>${flavourA}</activeByDefault>
</activation>
<modules>
<module>profiled-module2</module>
<module>profiled-module3</module>
</modules>
</profile>
<profile>
<id>flavourB</id>
<activation>
<activeByDefault>${flavourB}</activeByDefault>
</activation>
<modules>
<module>profiled-module3</module>
</modules>
</profile>
<profile>
<id>flavourC</id>
<activation>
<activeByDefault>${flavourC}</activeByDefault>
</activation>
<modules>
<module>profiles-module1</module>
<module>profiled-module2</module>
<module>profiled-module3</module>
</modules>
</profile>
</profiles>
The archetype-metadata.xml file could then specify:
<requiredProperties>
<requiredProperty key="flavourA">
<defaultValue>false</defaultValue>
</requiredProperty>
<requiredProperty key="flavourB">
<defaultValue>false</defaultValue>
</requiredProperty>
<requiredProperty key="flavourC">
<defaultValue>false</defaultValue>
</requiredProperty>
</requiredProperties>
And the archetype invoked with the -DflavorB=true option would then generate a pom as following:
<profiles>
<profile>
<id>flavourA</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<modules>
<module>profiled-module2</module>
<module>profiled-module3</module>
</modules>
</profile>
<profile>
<id>flavourB</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>profiled-module3</module>
</modules>
</profile>
<profile>
<id>flavourC</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<modules>
<module>profiles-module1</module>
<module>profiled-module2</module>
<module>profiled-module3</module>
</modules>
</profile>
</profiles>
Such an approach has the following advantages and disadvantages:
Advantages
You keep the common modules and the archetype maintenance in one centralized place, while leaving the choice of flavors to the user of the archetype
Users of the archetype could, if desired and with zero-cost, switch from one flavor to another just activating/deactivating profiles
The approach uses standard Maven features
Disadvantages
Each archetype will generate the whole set of modules, even though not all of them will be required
If really a "noise", the user could manually delete the undesired modules, but still it would be a manual action
Moreover, on top of the approach above, we could also configure the Maven Clean Plugin in each profile to delete the modules not concerned by its flavor, so that at its first build (a maven clean), any non required module would be deleted. Such an approach would leave the POM with inconsistent profiles though, but it might be considered as well (not recommended).
Something like:
<profile>
<id>flavourA</id>
<activation>
<activeByDefault>${flavorA}</activeByDefault>
</activation>
<modules>
<module>profiled-module2</module>
<module>profiled-module3</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<filesets>
<fileset>
<directory>${basedir}/profiled-module1</directory>
</fileset>
</filesets>
</configuration>
</plugin>
</plugins>
</build>
</profile>
I have forked the project and added a feature to enable or disable the generation of submodules based on properties passed to the Maven session.
See https://github.com/manouti/maven-archetype.
By setting -DgenerateEnableProperties=true when calling the create-from-project goal, the plugin would create enabler properties for each child module in the form generate.module.X. When calling the generate goal thereafter, one can exclude a module by passing -Dgenerate.module.X=false.
Alternatively:
You may be able to workaround this using partial archetypes by setting partial="true" in the descriptor, which allows the generation of a project on top of an existing project. This post seems to tackle the same issue.
Then you can write a script that takes the desired properties and generates the corresponding parts of the project using the partial archetypes, e.g. using Ant:
<target name="mvn.generate.project.module1" if="generate.module1">
<exec dir="." executable="sh">
<arg value="-c" />
<arg value="mvn archetype:generate -DarchetypeGroupId="com.example.project" -DarchetypeArtifactId="archetype1" ..." />
</exec>
</target>
<target name="mvn.generate.project.module2" if="generate.module2">
<exec dir="." executable="sh">
<arg value="-c" />
<arg value="mvn archetype:generate -DarchetypeGroupId="com.example.project" -DarchetypeArtifactId="archetype2" ..." />
</exec>
</target>
Update (6/11/16):
A related issue is https://issues.apache.org/jira/browse/ARCHETYPE-494. From the description of the committer:
There you can specify a groovy file, which will be executed after the archetype generation. I personally use this groovy file to do something similar: I read properties from the command line and then remove declared dependencies, classes and jsp files which the user might not need.
I think what you are asking is in the context of this issue:
https://issues.apache.org/jira/browse/ARCHETYPE-494
I have it already implemented and will be included in the next version of the maven archetype plugin. There you can specify a groovy file, which will be executed after the archetype generation. I personally use this groovy file to do something similar: I read properties from the command line and then remove declared dependencies, classes and jsp files which the user might not need.
Please let me know if that helps.

Inherit only some properties or some plugins from parent poms

We have Oracle ADF and SOA projects that are built using custom Ant scripts, instead of normal Maven build. The same Ant plugin is configured differently for ADF and for SOA. The file structure isn't driven by the type of the project, but can be mixed, meaning:
- parent pom
- ADF
- SOA type1
- SOA type2
How can we set in the pluginManagement different versions of Ant plugins, and the children to pick whatever type of Ant plugin they want. As I know you can only pick what plugins you want, but not what flavor of same plugin.
I don't want to complicate my inheritance structure just for this. I need the structure to remain as it is, for release purposes.
The same I want with properties, I want to have some types of properties in central places, and a project to be able to use them, but also inherit the parent pom (for release purposes). Sort of like inherit from multiple parents.
I don't want to be tight by the need of properties and plugins (which are general for all projects, not just mine). I need to keep my pom structure clean, for release purposes.
You could try using profiles. They allow for the ability to customize a particular build for a particular scenario.
You can define multiple profiles in your parent pom each containing their own ant <plugin> section. Each profile would also have activation section. Then in your child modules you would have them activate the appropriate profile.
I'll try and give an example using some sudo code:
parent pom
<profile>
<id>adf-project</id>
<build>
<plugins>
<plugin>
<!-- adf specific ant plugin config -->
</plugin>
</plugins>
</build>
<activation>
<property>
<name>adfBuild</name>
<value>true</value>
</property>
</activation>
</profile>
<profile>
<id>soa-project</id>
<build>
<plugins>
<plugin>
<!-- soa ant plugin specific config -->
</plugin>
</plugins>
</build>
<activation>
<property>
<name>soaBuild</name>
<value>true</value>
</property>
</activation>
</profile>
Then in your soa module pom you would have the following:
<project ...>
<properties>
<soaBuild>true</soaBuild>
</properties>
</project>
This will then automatically activate that profile and use the correct ant plugin configuration.
Another option would be to define the plugin as normal but with multiple executions (one execution for soa and one for adf) and then in the child poms override each execution with a phase of none for those executions that you do not want to run. It should be noted that this latter approach is not recommended. See my answer here for more details on this.

Maven: filtering seam components.xml in target directory

I'm trying to convert an Ant project to Maven. The existing build uses Ant-style properties in src/main/webapp/WEB-INF/components.xml, which is a Seam file.
I'm able to get the properties expanded in the actual resulting war file, via the maven-war-plugin. But I can't seem to get the properties expanded in target/myproject/WEB-INF/components.xml.
This means that when I try to run the Jetty plugin, it doesn't see the expanded properties.
I tried defining the properties in both an external file, and also right in the build. My profile section looks like the following:
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<filters>
<filter>src/main/filters/components-dev.properties</filter>
</filters>
</build>
<properties>
<debug>true</debug>
<jndiPattern>FOO</jndiPattern>
</properties>
</profile>
</profiles>
When you run mvn jetty:run it executes the lifecycle up through test-compile. The web resources don't get filtered until the war plugin runs as part of package. I found a question on stackoverflow that seems similar, does that solution work for you?

How to generate a combined Maven site from unrelated projects?

I would like to create a general overview of several Maven projects in the form of a website generated with the Maven site goal. The projects are part of different products, some have a parent-child relation, some have dependencies on others.
The site should combine the information from all projects and include JavaDoc, Checkstyle/PMD checks, test results and code coverage metrics.
I've created a POM file that aggregates each existing project as a module, with each project available in subfolder, but then the output is not combined into a single site.
You can do this by setting project.build.directory on all of your projects to a common folder. This can be accomplished by passing in the path as a parameter to the build. You can then run the site goal on the common target folder. If you run maven from in a continuous integration environment, you can do this by setting targetpath in your maven task. Otherwise you would have to specify it on the command line.
<project>
<build>
<directory>${targetpath}/${project.artifactId}</directory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>2.3</version>
<configuration>
<inputDirectory>${targetpath}</inputDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>
mvn clean deploy -Dtargetpath=Path/To/Build/Output
To keep the build the same for your developers, you could create a profile that is activated when targetpath is not provided by the command line.
<profiles>
<profile>
<id>dev</id>
<activation>
<property>
<name>!targetpath</name>
</property>
</activation>
<properties>
<targetpath>target</targetpath>
</properties>
</profile>
</profiles>

Resources