I am building this multi-module project with Maven. The folder structure of the project at root is as follows:
core (dir)
|--- pom.xml
|--- pom (dir)
|---com.loc.dist.core.msp.osgi.pom (dir)
|---pom.xml
|--- com.lgc.dist.core.msp.example.helloservice.client (dir)
|---pom.xml
Project com.lgc.dist.core.msp.example.helloservice.client is packaged as OSGI bundle and it is a child module of com.loc.dist.core.msp.osgi.pom
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.lgc.dist</groupId>
<artifactId>com.lgc.dist.core.msp.osgi.pom</artifactId>
<relativePath>../pom/com.lgc.dist.core.msp.osgi.pom</relativePath>
<version>0.1</version>
</parent>
<artifactId>com.lgc.dist.core.msp.example.helloservice.client</artifactId>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>com.lgc.dist</groupId>
<artifactId>com.lgc.dist.core.msp.service</artifactId>
<version>0.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Export-Package>com.lgc.dist.core.msp.example.helloservice.client.*;version=${project.version}</Export-Package>
<Private-Package>com.lgc.dist.core.msp.example.helloservice.client.internal</Private-Package>
<Import-Package>*</Import-Package>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
The pom.xml in top level shows pom folder and com.lgc.dist.core.msp.example.helloservice.client are in the reactor list.
<modules>
<module>pom</module>
<module>com.lgc.dist.core.msp.example.helloservice.client</module>
</modules>
When I ran mvn clean install from the root, it tends to build com.lgc.dist.core.msp.example.helloservice.client back to back twice. It is ok to install twice, but it will cause trouble when I run mvn deploy. All other submodules just built once. It is only the child modules of com.loc.dist.core.msp.osgi.pom are being built twice. I guess osgi builds all the bundle modules by default. But if I comment it out in pom.xml, the osgi bundle modules won't get built at all. What should I do to build these OSGI bundles just once?
EDIT It works fine if I change the packaging mode from bundle to jar, but that negates the purpose of having OSGI bundles.
Since the project "com.lgc.dist.core.msp.example.helloservice.client" is not a direct child of top level pom.xml, remove it from there.
So, in top level pom.xml, the entries should be :
<modules>
<module>pom/com.loc.dist.core.msp.osgi.pom</module>
</modules>
And pom.xml in pom/com.loc.dist.core.msp.osgi.pom should be having :
<modules>
<module>com.lgc.dist.core.msp.example.helloservice.client</module>
</modules>
After some research, it turns out maven-bundle-plugin 2.5.4 deploys the bundles by default. According to one of the answers of When using “bundle” packaging with maven-bundle-plugin goals are executed twice
(I'm surprised it did not get any up votes), you need to stop deploying by adding the execution block
<executions>
<execution>
<id>default-deploy</id>
<phase>no-execute</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
It is working now.
EDIT, based on the comment of this answer, it is resolved in 2.5.5. Haven't tried it though.
Related
I have a multi-module maven project that is used to produce a single spring boot fat jar. My project looks something like this.
- Parent Module Aggergator
- A
- B
- C
- app <-- app.jar is the only thing I want to publish
In my case module A, B, C are only ever used by app and should not be published into maven repo. I have split up the app into multi-module project because it's a lot of code in the app and it's to work with that way.
Currently the app.jar will contain inside it a.jar, b.jar c.jar.
Is there a way to tell maven that the compiled classes from module A, B, C should just be inserted into app.jar classes folder without ever producing A.JAR, B.JAR, C.JAR?
I use the Maven Shade Plugin for my multi-module project; it creates a single JAR and extracts each module into it rather than creating multiple JAR files:
Parent pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<groupId>...</groupId>
<artifactId>pipeline</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>firehose</module>
<module>gson</module>
<module>lambda</module>
<module>mapper</module>
<module>model</module>
<module>receiver</module>
<module>redshift</module>
<module>reloader</module>
<module>s3</module>
<module>sns</module>
<module>sqs</module>
<module>systemstests</module>
<module>transaction</module>
<module>utility</module>
</modules>
<dependencies>
...
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Child pom.xml (the JAR):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>...</groupId>
<artifactId>pipeline</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>lambda</artifactId>
<dependencies>
...
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<finalName>MyJar</finalName>
</configuration>
</plugin>
</plugins>
</build>
</project>
Here is a non answer.
Is there a way to tell maven that the compiled classes from module A,
B, C should just be inserted into app.jar classes folder without ever
producing A.JAR, B.JAR, C.JAR?
You could use the repackage goal of the spring boot maven plugin that flatten the dependencies into classes in the uber jar.
In my case module A, B, C are only ever used by app and should not be
published into maven repo.
Adding the modules in a local repository is really wanted to have a efficient and standard build.
Without that, you will need to compile systematically each module at each time you want to run your spring boot app.
While actually sometimes you need to build dependencies, but other times you don't need because these are already updated.
Or else you will be constraint to twist the default Maven way of work by adding manual tasks to compile from the spring boot module the other modules and to move the compiled classes into the spring boot module. Really not a gift for the people that will have to read/maintain this configuration.
I'm turning a single Eclipse Maven-managed webapp project in a multi-module Maven project (this is a test project to experiment with Maven, so feel free to provide any kind of suggestion).
The single project webapp doean't have any error, succesfully compiles and behaves correctly when deployed, so I'm starting with a working application.
The application has a web part and a console part, meaning that there are some classes with a main() method that when run from within Eclipse (with Run as -> Java Application) work as expected. Both parts show data from a database, queried either directly through JDBC or through jOOQ.
So, this is how I split the project:
core (holds everything common to the other two parts);
runnable (contains the classes that have a main() method);
webapp (the web application part).
Inside Eclipse, I have now 4 separate projects:
shaker-multi holds the aggregator (and parent) POM, plus each module in a subdirectory;
shaker-multi-core;
shaker-multi-runnable;
shaker-multi-webapp.
Inside Eclipse, core and webapp compile, and the latter can be deployed to a Tomcat instance and I can see it in the browser.
The problem arises with runnable. That project relies on jOOQ classes, so the relevant source code must be generated. The jOOQ dependencies and configuration are in core/pom.xml (since they may be used there too).
When I do Project -> Run As -> Maven build... -> clean generate-sources, on shaker-multi-core I get:
Non-resolvable parent POM: Failure to find sunshine.web:shaker-multi:pom:0.0.1
which sounds reasonable, since I didn't install any of those artifacts, even in my local repository.
But when I call Maven build... -> 'clean install' on shaker-multi, it breaks because it can't find the web.xml file for shaker-multi-webapp (although it correctly resides in shaker-multi-webapp/src/main/webapp/WEB-INF/web.xml).
What should I do?
Is my project configuration / splitting totally wrong?
Should I add another module with the parent POM? This sounds wrong, since the POM Reference states:
Inheritance and aggregation create a nice dynamic to control builds through a single, high-level POM. You will often see projects that are both parents and aggregators.
I'm totally lost here.
My expectations:
run Maven package on shaker-multi-webapp and obtain a deployable war;
run Maven package on shaker-multi-runnable and obtain a command line runnable jar (I still need to configure its POM to generate a jar-with-dependencies, though, I know);
run Maven package on shaker-multi and obtain some kind of bundle that I can move around and that will contain the war or the jar of each module.
EDIT
I added
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
</configuration>
</plugin>
to shaker-multi-webapp POM, as seen in this answer, but with no difference.
EDIT-2
I cleared my whole local repository (as suggested here), and when I reopened Eclipse, in the Maven console I saw
[...]
05/09/14 07:58:19 CEST: [INFO] Adding source folder /shaker-multi-webapp/src/main/java
05/09/14 07:58:19 CEST: [INFO] Adding source folder /shaker-multi-webapp/src/test/java
**05/09/14 07:58:19 CEST: [ERROR] Could not read web.xml**
[...]
Any hint? From where does it come from? I can't reproduce it though (without removing again my whole local repo).
This is shaker-multi POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>sunshine.web</groupId>
<artifactId>shaker-multi</artifactId>
<version>0.0.1</version>
<packaging>pom</packaging>
<modules>
<module>shaker-multi-core</module>
<module>shaker-multi-runnable</module>
<module>shaker-multi-webapp</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
This is shaker-multi-core POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>sunshine.web</groupId>
<artifactId>shaker-multi</artifactId>
<version>0.0.1</version>
</parent>
<artifactId>shaker-multi-core</artifactId>
<packaging>jar</packaging>
<build>
<plugins>
<plugin><!-- jOOQ plugin--></plugin>
</plugins>
</build>
<dependencies>
<dependency><!-- jOOQ dependency --></dependency>
</dependencies>
</project>
This is shaker-multi-webapp POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>sunshine.web</groupId>
<artifactId>shaker-multi</artifactId>
<version>0.0.1</version>
</parent>
<artifactId>shaker-multi-webapp</artifactId>
<packaging>war</packaging>
<build>
<plugins>
<plugin><!-- Tomcat local -->
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>sunshine.web</groupId>
<artifactId>shaker-multi-core</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<!-- JSP & Servlet dependencies -->
</dependency>
</dependencies>
</project>
I assume you folder structure is like this:
+-- shaker-multi
+--- pom.xml
+--- shaker-multi-core
+-- pom.xml
+--- shaker-multi-runnable
+-- pom.xml
+--- shaker-multi-webapp
+-- pom.xml
Furthermore you should check if your project works correctly on command and
NOT in Eclipse. So you should go to the root of your project
(shaker-multi folder) and
mvn clean package
This should produce no error etc.
One thing which comes into my mind is why do you use a release version instead of
a SNAPSHOT version for your project. So 0.0.1 instead of 0.0.1-SNAPSHOT?
A thing which you should improve is the definintion of maven-compiler plugin
in your parent:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
I would suggest to do it this way:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
The encoding can be solved in a better way just define the following in your pom:
<project>
...
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
...
</project>
The above will define the default value for many plugin like maven-compiler-plugin,
maven-resources-plugin etc.
part from that your structure looks good ...one small improvement i would
suggest is if you define dependencies between your module:
<dependencies>
<dependency>
<groupId>sunshine.web</groupId>
<artifactId>shaker-multi-core</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<!-- JSP & Servlet dependencies -->
</dependency>
</dependencies>
I would suggest to define inter module dependencies like this:
<dependencies>
<dependency>
<groupId>sunshine.web</groupId>
<artifactId>shaker-multi-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<!-- JSP & Servlet dependencies -->
</dependency>
</dependencies>
The whole problem here was really simple, and I feel a bit ashamed about it: but being the first time I did a multi–module project, I guess that could happen.
Of course, the details here hold when you work with all the project and modules sources by yourself: if you're in a team, working on only a part of the project and / or with a centralized private repository, then YMMV.
First of all, after I splitted the single–project into several modules, this was the situation in my Eclipse Project Explorer:
+-- shaker-multi
^--- pom.xml
^--- shaker-multi-core
^-- pom.xml
^-- (other content)
^--- shaker-multi-runnable
^-- pom.xml
^-- (other content)
^--- shaker-multi-webapp
^-- pom.xml
^-- (other content)
+-- shaker-multi-core
^-- pom.xml
+-- shaker-multi-runnable
^-- pom.xml
+-- shaker-multi-webapp
^-- pom.xml
Each +-- is a single, separated, Eclipse project. Each one of them has been singularly checked out from SVN (so they were, in fact, detached from one another).
I was, then, editing something in +-- shaker-multi-runnable and expecting that to work when I was running Maven on +-- shaker-multi, without svn–committing the former and svn–updating the latter.
That's why I kept getting the error in this question!
The proper way to handle such projects, if they come from an originally monolithic project is:
to split the code, resources, etc in subfolders;
to commit every change to the repository;
to erase every involved project in Eclipse.
Next, you go in the SVN Repositories tab of the IDE, expand the repository with the now splitted project and do Check out as Maven project of the parent–project (the one that has modules as subfolders).
If you, like me, are working with a recent version of Subclipse, you'll need the Maven Eclipse (m2e) SCM connector for subclipse 1.10 (svn 1.8) - update site (thanks go to buluschek development, see the last comments on that post), so that you can choose the repository path from the Check out as Maven Project dialog.
With it, you tell Eclipse to checkout the whole project from the parent folder, and the Eclipse automatically:
fetches all the Maven project modules;
creates a project corresponding to the parent–project, where modules are subfolders;
creates a separate project for every single module
links together each module project with the parent project, so that each edit in a module source code, resource, POM, etc is instantly reflected inside the folders of the parent-project.
That point (4) is the key here: although there are several projects, they have been linked together (I guess the same can be done when manually checking out each module folder, although I do not know how).
After having done this, all the Maven problems I had disappeared.
I am working on a new project which is a plugin for a product.
I use maven to build my plugin (zip) but I need to reference the source code of the product which is defined in my Eclipse workspace. But this source code is not managed by Maven and I do not want to migrate it.
Is it possible to refers this workspace project by any way? (maven plugins, workaround welcome).
The dependency is just needed for the compilation inside Eclipse but will not be packaged in the plugin itself (provided scope).
I have also m2e in Eclipse and I want to keep this configuration when I make a "Maven Update".
UPDATE: I am looking for a solution which will work with a mvn clean install on a command line because I want to be able to execute the build from a CI platform (e.g. Jenkins)
Simply use Project -> Properties -> Java Build Path -> Projects -> Add
If you need to compile it outside Eclipse you can add a dependency to physical jar location:
<dependency>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/lib/test.jar</systemPath>
</dependency>
You might consider using the antrun plugin to trigger the compilation of your source code in the external project linked to your compile phase. You could even copy your .class files into your target folder so the runtime classpath finds them
Because I have already the compiled source and I do not need to recompile them (or to modify anything) I decided to package them using the pom assembly.
I made a separate project (under the same parent's than my plugins developement projects) called like openemm-src:
Parent project (openemm-plugin-dev)
|- plugin-1
|- plugin-2
|- openemm-src
|- pom.xml
The pom.xml for the openemm-src project looks like:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>openemm.plugin.dev</groupId>
<artifactId>plugin</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>openemm-src</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<name>OpenEMM Source Code Library</name>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/assembly/src-plugin.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
<xecution>
</executions>
</plugin>
</plugins>
</build>
</project>
and the file src/assembly/src-plugin.xml:
<assembly>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>build/classes</directory>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
</assembly>
After this, I refers the jar from the siblings projects like this:
<dependency>
<groupId>openemm.plugin.dev</groupId>
<artifactId>openemm-src</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
This solution is looking more like a workaround, but this is because the OpenEMM project does not have any "Plugin Template Project" to be managed with Maven.
Note this is just a partial configuration and I had also to refers to the Agnitas libraries which did not contains all the source code (both were necessary to compile my code).
Provided two Maven projects: J (jar), W (war); both depend on one parent P (pom). The parent has a plugin, which must only run for the project "W".
How does one go about doing this:
without creating separate parent projects
without using a profile (so build must still be executed with mvn clean package)
J (jar)
<project>
<parent>
<artifactId>P</artifactId>
</parent>
<artifactId>J</artifactId>
<packaging>jar</packaging>
</project>
W (war)
<project>
<parent>
<artifactId>P</artifactId>
</parent>
<artifactId>W</artifactId>
<packaging>war</packaging>
</project>
P (pom)
<project>
<artifactId>P</artifactId>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>classes</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
I think you can achieve this using Profile Activation. Ideally, the activation condition would be something like "packaging type is war", but apparently, this condition cannot be implemented in Maven. However, in your case, there is a condition that can be implemented and that is probably equivalent in practice: "there is a src/main/webapp directory".
This is how your pom.xml might look like:
<profiles>
<profile>
<activation>
<file>
<exists>src/main/webapp</exists>
</file>
</activation>
<build>
[plugin configuration]
</build>
</profile>
</profiles>
One way to do this would be to place the plugin in the parent pom within <pluginManagement> section. Thereafter specify the plugin in the project(s) that you want it to run.
In your case, you would specify the plugin for project J and not W.
P
<build>
...
<pluginManagement>
<plugins>
<plugin>
<groupId>...</groupId>
<artifactId>...</artifactId>
... other plugin details ...
</plugin>
</plugins>
</pluginManagement>
...
</build>
J
<build>
...
<plugins>
<plugin>
<groupId>...</groupId>
<artifactId>...</artifactId>
<plugin>
</plugins>
...
</build>
Short answer: Maven doesn't appear to have a good way to do what you're trying to do. I've spent a fair amount of time trying to solve a similar problem and haven't found anything satisfactory.
You've already discovered two of the possible solutions: introduction of an additional parent pom for the wars (perhaps the additional pom extends the original parent so you don't have to duplicate all of its config), or duplicating the jar plugin config in all of the war poms. As you've said, neither of these is ideal.
Another possibility is to use the maven-assembly-plugin instead of the jar plugin to build the classified jar for the war projects. The assembly plugin is not included in the default lifecycles for either jar or war packaging, so you could configure it in the parent's <pluginManagement> section and then only reference it in the war projects as Raghuram described. If you need a custom assembly descriptor you will probably want to follow the sharing the assembly descriptors example.
This is my parent pom.xml (part of it) in a multi-module project:
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
…
This configuration instructs mvn to execute checkstyle plugin in the root project and every sub-module. I don't want it to work this way. Instead, I want this plugin to be executed only for the root project, and be skipped for every sub-module. At the same time, I have many sub-modules, and I don't like the idea of explicitly skipping the plugin execution in every one of them.
Documentation for Checkstyle says "..ensure that you do not include the Maven Checkstyle Plugin in your sub modules..". But how can I ensure that if my sub-modules inherit my root pom.xml? I'm lost, please help.
But how can I ensure that if my sub-modules inherit my root pom.xml?
To strictly answer this question, you can specify an <inherited> element inside a <plugin> definition. From the POM Reference:
inherited: true or false, whether or not this plugin configuration should apply to POMs which inherit from this one.
Something like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<!-- Lock down plugin version for build reproducibility -->
<version>2.5</version>
<inherited>true</inherited>
<configuration>
...
</configuration>
</plugin>
Some more advices/remarks (that may not apply):
You should always lock down plugin version for build reproducibility (you can enforce this rule with the Maven Enforcer Plugin).
People usually wants to use a a Custom Checkstyle Checker Configuration and/or a Suppressions Filter.
The Multimodule Configuration describes a typical setup allowing to share configuration files in large multimodules projects.
Perhaps you should separate your root pom into 2 separate entities: parent pom and aggregator pom. Your aggregator pom may even inherit from parent pom.
If you download latest project layout for hibernate, you will see this design pattern in action.
After this separation is done, you can define and execute checkstyle plugin just in aggregator/root pom. Because it is no longer a parent of your submodules it will not get inherited by them.
EDIT
Use <relativePath> when declaring <parent>
Just for demonstration, below is an example taken from the hibernate project structure.
The whole distribution can be found here-> http://sourceforge.net/projects/hibernate/files/hibernate3
Just so, that you have some context, here is a subset of their directory layout
project-root
|
+-pom.xml
|
+ parent
| |
| +-pom.xml
|
+ core
|
+-pom.xml
.. rest is scipped for brevity
project-root/pom.xml fragment
<parent>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-parent</artifactId>
<version>3.5.4-Final</version>
<relativePath>parent/pom.xml</relativePath>
</parent>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<packaging>pom</packaging>
<name>Hibernate Core Aggregator</name>
<description>Aggregator of the Hibernate Core modules.</description>
<modules>
<module>parent</module>
<module>core</module>
project-root/parent/pom.xml fragment
<groupId>org.hibernate</groupId>
<artifactId>hibernate-parent</artifactId>
<packaging>pom</packaging>
<version>3.5.4-Final</version>
project-root/core/pom.xml fragment
<parent>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-parent</artifactId>
<version>3.5.4-Final</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<packaging>jar</packaging>