SoftwareEntwicklung Beratung Schulung

A coders, hackers heaven.....Hm...I do not think so...

Maven Incremental Module Build

| Comments

If you are working with a Maven Multi Module Build on command line it could happen that you might think: Wouldn’t it be nice to build only the modules which you have changed and not all modules in the reactor.

You can of course control what you build by using the --projects command line option and add the appropriate modules you would like to build. For example like this:

1
mvn --projects module1,module2 clean package

But you need to think everytime you run the build about which modules have been changed and you need to adapt the list of changed modules manually.

Apart from that you need to think about the case if your modules are used by other modules in your build. This means module1 is a module dependency of another module. This can simply handled by Maven automatically by using the command line option --also-make-dependents which will build the modules which are dependencies of the modules given in the projects list.

1
mvn --projects module1,module2 --also-make-dependents clean package

There are often suggestions to change into the directory of the module you would like to build but this is simply wrong. If you start the build there Maven will read only the pom file of that single module and you have no chance of letting Maven anlyze the modules and their needed order etc. So always keep in the root directory of your multi module build and select the appropriate modules via --projects option.

The above will of course fine but this is cumbersome.

All this steps I have described can be handled in an automatic way by using the The Incremental Module Builder extensions.

To use the Incremental Module Build you need to run at best Maven 3.3.1+ and Java 7 as Maven 3.3.1+ itself. Furthermore you should configure it via the extensions.xml file in the .mvn/ folder of your project which should look like this:

1
2
3
4
5
6
7
8
<extensions xmlns="http://maven.apache.org/EXTENSIONS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/EXTENSIONS/1.0.0 http://maven.apache.org/xsd/core-extensions-1.0.0.xsd">
  <extension>
    <groupId>com.soebes.maven.extensions</groupId>
    <artifactId>incremental-module-builder</artifactId>
    <version>0.1.0</version>
  </extension>
</extensions>

Another prerequisite is having configured correctly the scm area in your root pom of the project cause those information are used to analyze for changed files. You can run the incremental module builder via:

1
mvn -b incremental package

which will printout something similar like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
~/ws-git/supose (master *)$ mvn -b incremental package
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] Subversion Repository Search Engine
[INFO] SupoSE :: Test
[INFO] SupoSE :: Filter
[INFO] SupoSE :: Filter : Filter Model
[INFO] SupoSE :: Filter : Filter
[INFO] SupoSE :: Core
[INFO] SupoSE :: CLI
[INFO] SupoSE :: WAR
[INFO] SupoSE :: Integration Test
[INFO] SupoSE :: Users Guide
[INFO] SupoSE :: Assembly
[INFO]  ------------------------------------
[INFO]  Maven Incremental Module Builder
[INFO]  Version: 0.1.0
[INFO]  ------------------------------------
[INFO]
[INFO] Using the IncrementalModuleBuilder implementation with a thread count of 3
[INFO] Executing: /bin/sh -c cd '/Users/kama/ws-git/supose' && 'git' 'rev-parse' '--show-toplevel'
[INFO] Working directory: /Users/kama/ws-git/supose
[INFO] Executing: /bin/sh -c cd '/Users/kama/ws-git/supose' && 'git' 'status' '--porcelain' '.'
[INFO] Working directory: /Users/kama/ws-git/supose
[INFO]  Changed file: supose-cli/pom.xml modified
[INFO] Changed Project: com.soebes.supose:supose-cli:jar:0.7.1-SNAPSHOT
[INFO] New Calculated Reactor:
[INFO]  SupoSE :: CLI
[INFO]  SupoSE :: Assembly
[INFO] Building project: com.soebes.supose:supose-cli:jar:0.7.1-SNAPSHOT
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building SupoSE :: CLI 0.7.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-enforcer-plugin:1.4.1:enforce (enforce-maven) @ supose-cli ---
[INFO]
[INFO] --- buildnumber-maven-plugin:1.4:create (default) @ supose-cli ---
[INFO] Executing: /bin/sh -c cd '/Users/kama/ws-git/supose/supose-cli' && 'git' 'rev-parse' '--verify' 'HEAD'
[INFO] Working directory: /Users/kama/ws-git/supose/supose-cli
[INFO] Storing buildNumber: 2cf6fbf37dbd3a0922ebd607a5b0504e76a0fd76 at timestamp: 1470779925110
[INFO] Storing buildScmBranch: master
[INFO]
[INFO] --- maven-resources-plugin:3.0.1:resources (default-resources) @ supose-cli ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.5.1:compile (default-compile) @ supose-cli ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:3.0.1:testResources (default-testResources) @ supose-cli ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.5.1:testCompile (default-testCompile) @ supose-cli ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.19.1:test (default-test) @ supose-cli ---

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.soebes.supose.cli.SuposeCLITest
Tests run: 22, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.527 sec - in com.soebes.supose.cli.SuposeCLITest

Results :

Tests run: 22, Failures: 0, Errors: 0, Skipped: 0

[INFO]
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ supose-cli ---
[INFO]
[INFO] --- maven-site-plugin:3.5.1:attach-descriptor (attach-descriptor) @ supose-cli ---
[INFO] Building project: com.soebes.supose:supose-assembly:pom:0.7.1-SNAPSHOT
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building SupoSE :: Assembly 0.7.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-enforcer-plugin:1.4.1:enforce (enforce-maven) @ supose-assembly ---
[INFO]
[INFO] --- buildnumber-maven-plugin:1.4:create (default) @ supose-assembly ---
[INFO]
[INFO] --- maven-site-plugin:3.5.1:attach-descriptor (attach-descriptor) @ supose-assembly ---
[INFO]
[INFO] --- appassembler-maven-plugin:1.10:assemble (default) @ supose-assembly ---
[INFO]
[INFO] --- maven-assembly-plugin:2.6:single (default) @ supose-assembly ---
[INFO] Reading assembly descriptor: src/main/assembly/bin.xml
[INFO] Reading assembly descriptor: src/main/assembly/bin-unix.xml
[INFO] Reading assembly descriptor: src/main/assembly/src.xml
[INFO] Building zip: /Users/kama/ws-git/supose/supose-assembly/target/supose-assembly-0.7.1-SNAPSHOT-bin.zip
[INFO] Building tar: /Users/kama/ws-git/supose/supose-assembly/target/supose-assembly-0.7.1-SNAPSHOT-bin-unix.tar.gz
[INFO] Building tar: /Users/kama/ws-git/supose/supose-assembly/target/supose-assembly-0.7.1-SNAPSHOT-src.tar.gz
[INFO] Building zip: /Users/kama/ws-git/supose/supose-assembly/target/supose-assembly-0.7.1-SNAPSHOT-src.zip
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] SupoSE :: CLI ...................................... SUCCESS [ 16.145 s]
[INFO] SupoSE :: Assembly ................................. SUCCESS [  2.425 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 18.853 s (Wall Clock)
[INFO] Finished at: 2016-08-09T23:59:02+02:00
[INFO] Final Memory: 27M/437M
[INFO] ------------------------------------------------------------------------

As you can see the Incremental Module Builder will analyze automatically which modules have been changed and will also build the dependent modules. There is one point which is not very convinient. You always need to give on command line the -b incrmental part. But this can be handled by using the .mvn/maven.config file with the following content:

1
-b incremental

form this point on you can do it simply via:

1
mvn package

If you like to prevent usage of the incremental module build you can simply force this by using this:

1
mvn -b multithreaded package

which is the default which is used by Maven.

Currently the Incremental Module Builder is in a proof of concept state but it works for me and helped me a lot. If you find issues please don’t hesitate to file in an issue report. Apart from that any feedback is welcome.

Maven: How to Create a Release

| Comments

You are working on your project and now the time has come where you would like to create a release of your project. So how to do this with Maven?

There are existing in general several solutions to achieve the goal. Those different solutions will be described in this article.

Maven Release Plugin

The most obvious one and probbaly most suggested variant is to use the Maven Release Plugin to create a release.

So as a short overview how the Maven Release plugins works is:

1
mvn release:prepare ..

So you call the prepare goal of the plugin which will do several checks to be sure you will get a reproducible state of your project. By default you can give the release version of your project interactivaly or if you like to take the defaults you can handle this via --batch-mode option. So after changing the pom file a build will run to make sure everything works well and finally a tag in your version control will be created and the next development version will be set in your pom files.

So next you will call the final part of Maven Release plugin the perform goal which will checkout the code you have tagged in the previous step and run deploy site-deploy on this checked out state. Often you call the above goal in one go which means:

1
mvn release:prepare release:perform --batch-mode

All your pom files will automatically updated with the new version etc. So no manual work needed here.

If you think about this scenario you might say: Why do I need to build my project during the release creation cause I already built my project before? The intention for the Maven Release Plugin is to use it from your own computer or where you do not have the support of a CI solution which creates the releases. Furhtermore this can also be based on the usage of GPG keys to sign artifacts etc. which only exist on your own machine so the Maven Release Plugin is a good way to handle releases from your own machine. Maven Release Plugin is also used to release all Maven Plugins of the Apache Maven Project.

Versions Maven Plugin

So an other variant to create a release can be achieved by using the Versions Maven Plugin which you can use to create a release.

What you have to do is more or less the same as Maven Release Plugin would do. You need to check if you missed to checkin sources etc. and afterwards you can change the pom versions of your project by using the following:

1
mvn versions:set -DnewVersion=1.0.0

and all pom versions will be changed accordingly. Now you can simply checkin the changed pom files and tag the code state and make:

1
mvn clean deploy

which will build your whole project and deploys the generated artifacts into the configured remote repositories. Now you would like to continue developement so you need to change the pom versions via:

1
mvn version:set -DnewVersion=1.0.1-SNAPSHOT

And you need to checkin in the changed pom files and now you can continue with your developement for the next release.

You can of course script the above steps or better is to move those steps into a CI solution like Jenkins.

This approach prevents some builds of your project but you need to change the pom versions and do some checkins.

Super Fast Releases

Starting with Maven 3.2.1 you can define the pom version by using the following possible properties: ${revision}, ${sha1} and ${changelist}. The example below will show one usage of this:

1
2
3
4
5
6
7
8
9
10
11
12
  ..
  <parent>
    <groupId>com.soebes.smpp</groupId>
    <artifactId>smpp</artifactId>
    <version>2.2.1</version>
  </parent>

  <groupId>com.soebes.examples.j2ee</groupId>
  <artifactId>parent</artifactId>
  <version>${revision}</version>
  <packaging>pom</packaging>
  ..

This is a parent of a larger multi module build which contains serveral childs which look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>com.soebes.examples.j2ee</groupId>
    <artifactId>parent</artifactId>
    <version>${revision}</version>
  </parent>

  <artifactId>service</artifactId>
  <dependencies>
    <dependency>
      <groupId>com.soebes.examples.j2ee</groupId>
      <artifactId>service-client</artifactId>
      <version>${project.version}</version>
    </dependency>
    ...

   ..

Based on that you can now build your project simply by using the following:

1
mvn -Drevision=1.0.0-SNAPSHOT clean package

or to deploy a SNAPSHOT you can simply do this via:

1
mvn -Drevision=1.0.0-SNAPSHOT clean deploy

So there is no need to change the pom files and checkin. But there exists a drawback. You need to define the -Drevision=... for every call of Maven which is not very convenient.

You can handle this by using the following profile:

1
2
3
4
5
6
7
8
9
10
11
12
13
  <profiles>
    <profile>
      <id>default-version</id>
      <activation>
        <property>
          <name>!revision</name>
        </property>
      </activation>
      <properties>
        <revision>1-SNAPSHOT</revision>
      </properties>
    </profile>
  </profiles>

which will define the revison in case the property has not been given on command line by using a default value 1-SNAPSHOT.

Starting with Maven 3.3.1 you can configure Maven command line parameters in a .mvn/maven.config file which contains the following for our case:

1
-Drevision=1.0.0-SNAPSHOT

So with Maven 3.3.1+ you can now simply call Maven via:

1
mvn clean deploy

More convenient? No profile needed.

But wait. What if i like to create a different version? Yes you need to change the .mvn/maven.config file and you should of course checkin the change in your version control.

Unfortunately you can’t overwrite the property which you have defined in the .mvn/maven.config via command line like this:

1
mvn clean deploy -Drevision=2.0.0-SNAPSHOT

This problem has already been adressed and solved for the upcoming Maven 3.4.0 release where you can simply do that via the latter.

Starting with Maven 3.4.0 you do not need a profile so you can define a default value for your revision in .mvn/maven.config file and overwrite the value always via command line. This is very convenient in CI tools etc. and furthermore eliminates the usage of those version numbers in your pom file which always produce conflicts if you do a merge from one branch to another.

Spoiler Alert: Upcoming Maven 3.4.0 - Changes - III

| Comments

Currently the preparations for the upcoming Maven 3.4.0 release is running. There had been informations about the changes for the next Maven release.

I will give some more information about changes which are (might be!) part of the next Maven release.

Just be warned that you do not blame me if a particular issue will not part of the final release. This is written from the current perspecitve. So no warranty about that.

I assume that you know filtering in resources can simply be achieved by configuring things like this in your pom file:

1
2
3
4
5
6
7
8
  ...
  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
    </resource>
  </resources>
...

But this configuration has one drawback. It will filter everything, except files with pre defined extensions like jpg, jpeg, gif, bmp, png.

Often in builds you need have supplemental files which should be filered or not filtered. So the consequence is to enhance the configuration and adding those extensions/folders etc. Or you know that you have some folders in that above tree which contain files which should not be filtered eithers. This often ends up with a bunch of includes/excludes etc. which is simply cumbersome.

The best and simplest solution would be having two different locations for filtered and non-filtered files. So a configuration in your pom could look like this:

1
2
3
4
5
6
7
8
9
10
11
  ...
  <resources>
    <resource>
      <directory>src/main/resources</directory>
    </resource>
    <resource>
      <directory>src/main/filtered-resources</directory>
      <filtering>true</filtering>
    </resource>
  </resources>
...

So this setup makes it easier and more clean where the files are located which will be filtered and the ones which will not. The same could of course be applied to the src/test area.

By improving the Conventions over Configuration paradigm in Maven 3.4.0 the super pom contains such an configuration for the src/main/resources, src/main/filtered-resources, as well as for the src/test/resources, src/test/filtered-resources.

MojoHaus Version Maven Plugin Version 2.3 Released

| Comments

The MojoHaus team is pleased to announce the release of the Versions Maven Plugin Version 2.3.

The Versions Plugin is used when you want to manage the versions of artifacts in a project’s POM.

To get this update, simply specify the version in your project’s plugin configuration:

1
2
3
4
5
<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>versions-maven-plugin</artifactId>
  <version>2.3</version>
</plugin>

MojoHaus Build Helper Maven Plugin Version 1.12 Released

| Comments

The MojoHaus team is pleased to announce the release of the Build Helper Maven Plugin Version 1.12.

This plugin contains various small independent goals to assist with Maven build lifecycle.

To get this update, simply specify the version in your project’s plugin configuration:

1
2
3
4
5
<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>build-helper-maven-plugin</artifactId>
  <version>1.12</version>
</plugin>

MojoHaus Build Helper Maven Plugin Version 1.11 Released

| Comments

The MojoHaus team is pleased to announce the release of the Build Helper Maven Plugin Version 1.11.

This plugin contains various small independent goals to assist with Maven build lifecycle.

To get this update, simply specify the version in your project’s plugin configuration:

1
2
3
4
5
<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>build-helper-maven-plugin</artifactId>
  <version>1.11</version>
</plugin>

Spoiler Alert: Upcoming Maven 3.4.0 - Changes - II

| Comments

Currently the preparations for the upcoming Maven 3.4.0 release is running. There had been informations about the changes for the next Maven release.

I will give some more information about changes which are (might be!) part of the next Maven release.

Just be warned that you do not blame me if a particular issue will not part of the final release. This is written from the current perspecitve. So no warranty about that.

If you like to create source packages during the release you can use the defined state in the super pom, but unfortunately there is little issue with the default definitions which causes the generate-resources and the generate-sources life cycle phase to run twice based on the bound goal of the maven-source-plugin which forkes the life cycle. So a typical workaorund is to detach the maven-source-plugin form the life cycle via the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  <pluginManagment>
    <plugins>
      ..
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-source-plugin</artifactId>
        <version>..</version>
        <executions>
          <execution>
            <id>attach-sources</id>
            <phase>DISABLE_FORKED_LIFECYCLE_MSOURCES</phase>
          </execution>
        </executions>
      </plugin>
      ..
    </plugins>
  </pluginManagment>
..

But to keep generating a source package during the release you need to add the following to your pom file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  <plugins>
    <plugin>
      <inherited>true</inherited>
      <artifactId>maven-source-plugin</artifactId>
      <executions>
        <execution>
          <id>attach-sources-no-fork</id>
          <inherited>true</inherited>
          <goals>
            <goal>jar-no-fork</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>

The above workaround is no longer needed cause the super pom has been changed accordingly to MNG-5940 and exactly contains the binding with the jar-no-fork goal.

Mojo Mock Repository Manager Plugin Version 1.0.0 Released

| Comments

Hi,

The MojoHaus team is pleased to announce the release of the Mock Repository Manager Maven Plugin version 1.0.0.

The Mock Repository Manager Plugin is used when you want to test Maven plugins against specific sets of dependencies in a repository.

This release has now Maven minimum 2.2.1 and JDK 6.

To get this update, simply specify the version in your project’s plugin configuration:

1
2
3
4
5
<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>mrm-maven-plugin</artifactId>
  <version>1.0.0</version>
</plugin>

Release Notes – Mojo’s Mock Repository Manager – Version 1.0.0

Enjoy,

The MojoHaus team.

Karl Heinz Marbaise