Creating an Empty Multi-Module Project with Maven and m2eclipse

Why Maven?

Maven is a popular, mature, open source build and project management tool that we’ll be using to manage our Java project.  It provides a lot of different functionality which can be expanded even more through creation of plugins.  Out of the box Maven gives us a few very important things.  First it will handle dependency management for our application that allows us to control dependency version and allows Maven to pull and package them for us.  Secondly it enforces a standard project folder layout that it will copy from when building our artifacts.  M2eclipse gives us the ability to create and manage Maven projects through our Eclipse IDE.

A typical Maven project folder layout looks like this

/src/main/java/each/package/part
/src/main/resources
/src/test/java/each/package/part
/src/test/resources

When we tell Maven to build our project it will compile (if necessary) and copy all the classes and resources under the /src/main folders.  The java folder is intended to hold our java source files.  It follows the convention of having a folder for each part of a packages path so com.mycompany.artifact.MyJavaClass will be stored at /src/main/java/com/mycompany/artifact/MyJavaClass.java on the file system.  At build time Maven will compile and copy java sources along with the folders into our artifacts /classes/ folder.  Maven will also directly copy any thing under /src/main/resources into the /classes/ folder as well.

Test folders follow the same conventions as the main code except that these classes will NOT be packaged in our artifact and instead will just be compiled and run during the build to verify all the code/test cases still pass.  This is an important part in our build process because it allows us to automatically compile and run our test and provide reporting and fail the build if tests fail.

One thing to understand about Maven is that it has an opinionated view on best practices for building and managing projects which a lot of people will cite when comparing it with other build tools that allow for more customization to the build process.  While some will say this is a negative, in reality it enforces a standard layout and allows for people to easily understand the build process of any project since Maven itself enforces its own build conventions.  Using older tools like Ant you can easily customize every stage of the build process to your liking, but this leads to inexperience developers creating large unmanageable build processes and requires that any new team members have to fully sit down and figure out how the build is configured versus just understand how Maven configures its builds.

Finally in the root of each Maven project there will be a POM file.  This is the main configuration file located in the root of all maven projects, including the parent and each module.

Why a Multi-Module Project instead of a standalone?

A single standalone project will contain all our business logic, web tier code, and all resources.  To make management of this code easier Maven allows us to create a hierarchical project tree where we can define standard project settings in our parent project and break out our business code into a separate project than our web tier code.

Lets look at example to understand why mutli-module projects are important.  You have a basic client facing web application that connects to a database and allows the user to update some records from their browser.  Now this project is complete and you decide you want to write another web application facing an internal helpdesk users that shares a lot of the same business code.  In a single module project you now will have to not only pull all the business logic code that you want, but also all the web tier code, which may be completely useless to your new web app or you might just end up copying all your business code into the new project and now need to maintain both sets.  You also have the issue where you need to copy and paste and maintain Maven dependencies and their versions in two project’s POM now instead of just one.

With a multi-module project we can solve the second issue by maintaining all our dependencies and versions in a parent project pom which will be inherited by our child projects.  That way we can continue to add as many child projects as we want and only need to update and maintain dependencies in one place.  We can address the first issue now but breaking our all our business logic into its own project under our Parent.  With our core business logic broken out we can easily declare this project as a dependency in each of the web applications we create.  Now both our internal and external projects will just declare the core business logic project as a dependency and we no longer need to worry about synchronizing changes in business logic across them.  All of this would also apply to having a project that needs a webapp and a batch application and many other cases.

One thing to understand with the Parent project is that it contains no code and does not produce a dependency.  It only provides common configuration across all the child projects and lets Maven know all the projects that are grouped and built together.  In our example case we would end up with two project artifacts, one for the internal and one for the external application, both packaging the core project artifact inside them.

Creating the Project

First thing we need to do is add the Maven Central Archetype catalog to our m2eclipse installation so that we can find the pom-root archetype.  Maven archetypes are just project skeletons that we can use to quickly startup a Maven project instead of creating all the folders ourselves.  In Eclipse open the Windows -> Preferences menu and select the Maven -> Archetypes settings.  Click Add Remote Catalog and enter http://repo1.maven.org/maven2/archetype-catalog.xml for the Catalog File and name it Maven Central.

Next right click the Project Explorer -> Other and select Maven -> Maven Project.  Hit next and when you reach the Select and Archetype menu select Maven Central from the drop down and search for pom-root and select it and hit next.  Finally populate the groupId and artifact name for your maven project and click finish and Maven will generate the Maven folders and a basic parent POM file.

Now that we have a parent Project we can start adding modules.  Again right click the Project Explorer -> Other but this type select Maven -> Maven Module.  Make sure the parent project you created is listed as the parent and give your new module a name.  Typically I name shared code/business logic core and the webapp as webapp with possible a prefix if there’s more than one webapp in the project. Click next and you can select the archetypes for your new modules, which I generally just choose maven-archetype-quickstart which will give you a very basic maven module.  For web projects you can also use the maven-archetype-webapp which will give you the same project layout as the quickstart but also add /webapp/WEB-INF/web.xml folder/file used for Java Servlet Apps and be configured to produce a war artifact.

Once you’ve done the above you should be able to add and launch the application from whichever server you have configured inside eclipse using the WTP, m2e and m2e-wtp plugins.  If you are missing any of the menus above or are unable to deploy your project then you might be missing those plugins.  Previously we setup and configured Eclipse to use WebSphere for our dev environment but the process should be very similar for setting up something like Tomcat or Jboss for those who aren’t required to deploy to the IBM server.

Dependency and Plugin Management

As we said our parent pom holds the configuration for all our plugins and dependencies to be pulled into our modules.  Let’s take a look at a few that we’ll need for most applications.


<dependencyManagement>

<dependencies>
 <dependency>
 <groupId>${project.groupId}</groupId>
 <artifactId>core</artifactId>
 <version>${project.version}</version>
 </dependency>

<dependency>
 <groupId>${project.groupId}</groupId>
 <artifactId>webapp</artifactId>
 <version>${project.version}</version>
 </dependency>
 </dependencies>

</dependencyManagement>

Theses are our child core and webapp modules we created.  The ${project.groupId} is a Maven variable for the projects groupId that we specificed and ${project.version} the projects current version.


<dependencies>
 <dependency>
 <groupId>${project.groupId}</groupId>
 <artifactId>core</artifactId>
 </dependency>

<dependencies>

Here we add the projects core module to the webapp pom so that we can access all the shared business code.


<build>
 <pluginManagement>
 <plugins>
 <plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-compiler-plugin</artifactId>
 <version>${plugin-version.compiler}</version>
 <configuration>
 <source>${build.java.version}</source>
 <target>${build.java.version}</target>
 </configuration>
 </plugin>
 <plugin>
 <artifactId>maven-war-plugin</artifactId>
 <version>${plugin-version.war}</version>
 <configuration>
 <failOnMissingWebXml>false</failOnMissingWebXml>
 </configuration>
 </plugin>
 <plugin>
 <artifactId>maven-jar-plugin</artifactId>
 <version>${plugin-version.jar}</version>
 </plugin>
 <plugin>
 <artifactId>maven-ear-plugin</artifactId>
 <version>${plugin-version.ear}</version>
 </plugin>

</plugins>

</pluginManagement>

</build>

This configures what plugin version we’ll be using for our projects.  We are locking down our war/jar/ear plugin compiler versions here.


<properties>
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<build.java.version>1.7</build.java.version>

<plugin-version.compiler>3.1</plugin-version.compiler>

<plugin-version.ear>2.8</plugin-version.ear>
 <plugin-version.jar>2.4</plugin-version.jar>
 <plugin-version.war>2.4</plugin-version.war>
 </properties>

Here we can define replacement properties for use in our pom files using the ${} syntax.  Here we have our plugin version as well as defining our java build version to 1.7 and setting the text sourceEncoding to UTF-8.

Additional Info

We’ve shown how to create a very basic Maven project inside of eclipse, but can achieve the same results using the Maven command line as well. See http://maven.apache.org/guides/getting-started/ for more details.

Also we haven’t gone into the POM, Mavens configuration file, but instead just wanted to go over the very basics of what Maven provides us, and how/why we’d want mult-module projects.  To learn more about Maven and how to configure and use it see http://www.sonatype.com/resources/books for a great set of free ebooks which will cover everything you’d every want to know about using Maven.

Leave a comment