Google

Oct 6, 2011

Maven interview questions and answers - inheritance vs aggregation



Q: How do you inherit dependencies or plugins  in Maven? How are sub modules aggregated?
A:

In Maven Inheritance, you will have a multi-module maven project where a centrally managed POM file contains all the “approved” versions of artifacts.  In this “parent” pom was a “dependencyManagement” section with all the preferred versions of libraries within the organization. When you build a child of this parent, Maven will retrieve this parent to merge the parent pom with the child pom. You can have a look to the entire pom.xml by running the command mvn help:effective-pom. This parent pom is also known as the reactor pom. The child modules like myproject-ui, myproject-security, etc will be inheriting the versions from the parent.

Like "dependencyManagement" the "pluginManagement" in parent contains plugin elements intended to configure child project builds that inherit from this one. However, this only configures plugins that are actually referenced within the plugins element in the children. The children have every right to override pluginManagement definitions.

As shown below, the child modules are aggregated. The principle is that every command that you run on on the parent (i.e. reactor pom) will also be run on all the sub-modules. The order of the modules will be defined by the Reactor, which will look at inter-modules dependencies to find which module must be built before the others. If there are no dependencies, then it will take the list of the modules as they are defined in the parent pom.xml.

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>
 <groupId>com.myproject</groupId>
 <artifactId>myproject-parent-build</artifactId>
 <packaging>pom</packaging>
 <version>${myproject.version}</version>
 <name>${project.artifactId}</name>
 <url>http://www.myorganization.com</url>

 <properties>
     <myproject.version>1.0.0</myproject.version>
  <seam.version>2.2.2.Final</seam.version>
  ...
 </properties>

 <dependencyManagement>
  <dependencies>
   <!-- jboss seam dependencies -->
   <dependency>
    <groupId>org.jboss.seam</groupId>
    <artifactId>jboss-seam</artifactId>
    <version>${seam.version}</version>
   </dependency>
   ...
  </dependencies>
 </dependencyManagement>

 <build>
  <plugins>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.1</version>
    <configuration>
     <source>1.6</source>
     <target>1.6</target>
    </configuration>
   </plugin>
   ...
  </plugins>

  <pluginManagement>
   <plugins>
    <plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-compiler-plugin</artifactId>
     <version>2.1</version>
     <configuration>
      <source>1.6</source>
      <target>1.6</target>
     </configuration>
    </plugin>
    ...
   </plugins>
  </pluginManagement>
 </build>

 ...

 <modules>
  <module>myproject-security</module>
  <module>myproject-content</module>
  <module>myproject-data</module>
  <module>myproject-ui</module>
  <module>myproject-analytics</module>
 </modules>
 
</project>



Child pom.xml . The parent tag defines the parent to inherit form.

<?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>
 <groupId>com.myproject</groupId>
 <artifactId>myproject-ui</artifactId>
 <version>${myproject.version}</version>
 <packaging>war</packaging>
 <name>${project.artifactId}</name>
 <url>http://www.myorganization.com</url>
 <parent>
  <groupId>com.myproject</groupId>
   <artifactId>myproject-parent-build</artifactId>
  <version>${myproject.version}</version>
 </parent>

 <build>
  <finalName>cashonline</finalName>

  <pluginManagement>
   <plugins>
    <plugin>
     ...
    </plugin>
    ...
   </plugins>
  </pluginManagement>
 </build>

 <dependencies>
  <dependency>
   <groupId>org.jboss.seam</groupId>
   <artifactId>jboss-seam</artifactId>
   <exclusions>
    <exclusion>
     <groupId>javax.el</groupId>
     <artifactId>el-api</artifactId>
    </exclusion>
   </exclusions>
  </dependency>
  
  ...

 </dependencies>

 
</project>


Q. Is this inheritance of dependencies a good idea?
A. It is a good idea when you only have say 5-10 sub modules (i.e. child modules). But, if you have 50+ child modules inheriting from the parent dependency management or plugin management will cause a re-release of anything inheriting from it. For example, if you have 20+ projects inheriting org.jboss.seam jar, and if that jar goes from 2.2.2.Final to 2.3, then you will have to re-release the 20+ projects inheriting from it. It appears that as of version 2.0.9, there is a new scope on a dependency called import to aggregate dependencies without inheriting them.

The example below shows aggregation without the parent tag. The scope "import" aggregates the "myproject-parent-build".

<?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>
 <groupId>com.myproject</groupId>
 <artifactId>myproject-ui</artifactId>
 <version>${myproject.version}</version>
 <packaging>war</packaging>
 <name>${project.artifactId}</name>
 <url>http://www.myorganization.com</url>
 
 <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.myproject</groupId>
                <artifactId>myproject-parent-build</artifactId>
                <version>${myproject.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
             ....
        </dependencies>
    </dependencyManagement>
 
 
 <dependencies>
  <dependency>
   <groupId>org.jboss.seam</groupId>
   <artifactId>jboss-seam</artifactId>
   <exclusions>
    <exclusion>
     <groupId>javax.el</groupId>
     <artifactId>el-api</artifactId>
    </exclusion>
   </exclusions>
  </dependency>
  
  ...

 </dependencies>

 
</project>


So, like you favor composition or aggregation over inheritance, in maven pom also favor aggregation over inheritance.


Q. What are the different dependency scopes have you used?
A. compile, provided, test, and import.

Compile means that you need the JAR for compiling and running the app. For a web application, as an example, the JAR will be placed in the WEB-INF/lib directory.

Provided means that you need the JAR for compiling, but at run time there is already a JAR provided by the environment so you don't need it packaged with your app. For a web app, this means that the JAR file will not be placed into the WEB-INF/lib directory.

Test scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases.

import scope is used to aggregate the specified POM with the dependencies in that POM's "dependencyManagement" section. This scope is only used on a dependency of type pom in the section and available only from Maven version 2.0.9.


You could also read other Maven Interview Questions and Answers at Java build tools - why use Maven?

Labels: , ,

3 Comments:

Blogger hi said...

Good Information... Thanks.

8:48 PM, September 11, 2012  
Anonymous Saravanan said...

Hi Arul,
Detailed explanations are good.

I have two questions regarding maven,
1.How to change maven central repository to our local folder(Not to use mirror repository like Nexus,Archiva,etc..).This is possible means give me example.
2.Is possible without internet,we are able to execute maven life cycle commands.

3:54 AM, September 22, 2014  
Anonymous Anonymous said...

yes it is possible to execute without internet

1:26 AM, November 28, 2014  

Post a Comment

Subscribe to Post Comments [Atom]

Links to this post:

Create a Link

<< Home