Maven (Part 6) - Building Other Types of Projects and Sub-Projects
Maven (Part 6) - Building Other Types of Projects and Sub-Projects

Maven (Part 6) - Building Other Types of Projects and Sub-Projects

in
  1. Building Other Types of Projects
  2. Building Multiple Projects Simultaneously

Building Other Types of Projects

The lifecycle is applicable to any project type. For instance, let’s create a simple web application in the base directory:

mvn archetype:generate \
    -DarchetypeGroupId=org.apache.maven.archetypes \
    -DarchetypeArtifactId=maven-archetype-webapp \
    -DgroupId=com.mycompany.app \
    -DartifactId=my-webapp

Note that these must be all in one line. This will create a directory named my-webapp, containing the following project descriptor:

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-webapp</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>
 
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
 
  <build>
    <finalName>my-webapp</finalName>
  </build>
</project>

Notice the <packaging> element—it tells Maven to build as a WAR. Navigate into the webapp project directory and try the command:

mvn package

You’ll see target/my-webapp.war has been built, and all the normal steps have been executed.

Building Multiple Projects Simultaneously

Maven has built-in support for dealing with multiple modules. In this section, we’ll demonstrate how to build both the WAR mentioned above and include the previous JAR in one go.

First, we need to add a parent pom.xml file above the other two modules in the directory, so it should look like this:

+- pom.xml
+- my-app
| +- pom.xml
| +- src
|   +- main
|     +- java
+- my-webapp
| +- pom.xml
| +- src
|   +- main
|     +- webapp

The created POM file should contain the following:

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>app</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>
 
  <modules>
    <module>my-app</module>
    <module>my-webapp</module>
  </modules>
</project>

We need the dependency on the JAR in the web app, so add it to my-webapp/pom.xml:

  ...
  <dependencies>
    <dependency>
      <groupId>com.mycompany.app</groupId>
      <artifactId>my-app</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
    ...
  </dependencies>

Finally, in the other two pom.xml files in the subdirectories, add the following <parent> element:

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <parent>
    <groupId>com.mycompany.app</groupId>
    <artifactId>app</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  ...

Now, execute the command from the parent directory:

mvn verify

You now have the WAR created in my-webapp/target/my-webapp.war, including the JAR:

$ jar tvf my-webapp/target/my-webapp-1.0-SNAPSHOT.war
   0 Fri Jun 24 10:59:56 EST 2005 META-INF/
 222 Fri Jun 24 10:59:54 EST 2005 META-INF/MANIFEST.MF
   0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/
   0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/
   0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/
3239 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/pom.xml
   0 Fri Jun 24 10:59:56 EST 2005 WEB-INF/
 215 Fri Jun 24 10:59:56 EST 2005 WEB-INF/web.xml
 123 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/pom.properties
  52 Fri Jun 24 10:59:56 EST 2005 index.jsp
   0 Fri Jun 24 10:59:56 EST 2005 WEB-INF/lib/
2713 Fri Jun 24 10:59:56 EST 2005 WEB-INF/lib/my-app-1.0-SNAPSHOT.jar

How does this work? First, the created parent POM (named app) defines the pom packaging and the list of modules. This tells Maven to operate on all projects in the project set, not just the current one (to override this behavior, you can use the --non-recursive command-line option).

Next, we tell the WAR that it needs the my-app JAR. This is done for several reasons:

  • To make any code in the WAR (there’s no code in this example) available on the classpath.
  • To ensure the JAR is always compiled before the WAR.
  • To instruct the WAR plugin to include the JAR in its lib directory.

You might have noticed that junit-4.11.jar is a dependency but doesn’t end up in the WAR. This is because of the <scope>test</scope> element—it’s only for elements needed for testing, so it’s not included in the web app like the compile-time dependency my-app.

The final step is including the parent definition. This ensures that even if the projects are released separately from the parent project, the POM can still be found in the repository.