Archive

Posts Tagged ‘Maven’

Maven – Bill Of Materials

December 29th, 2013 1 comment

As I have been playing with Spring Boot (more on that in the coming blogs), I came across Maven’s Bill of Materials or BOM. Before I get into the details of BOM, let’s look at a common problem with lot of Spring projects. Here is a pom.xml snippet from a Spring Web Project that uses Spring Data JPA:

   <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-jpa</artifactId>
      <version>1.0.3.RELEASE</version>
   </dependency>
<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context</artifactId>
    <version>${org.springframework-version}</version>
    <exclusions>
        <!-- Use SLF4J. Not commons logging -->
        <exclusion>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
         </exclusion>
    </exclusions>
</dependency>

If you observe, the above configuration would pull different versions of Spring dependencies:

Blog 1

As you can see from the Dependency Hierarchy picture below, Spring Data JPA is pulling an older version of Spring Core.
Maven BOM

This intermixing of different versions of Spring (or any other library as a matter of fact), is not desirable and can cause unexpected issues. Of Course, this can be fixed by explicitly adding spring-core dependency.

This is where Maven’s “bill of materials” or BOM comes into picture. A BOM is simply a pom.xml file that contains a list of dependencies and their corresponding versions declared under dependencyManagement section. The set of artifacts defined in a BOM make up a “library” or a “stack”. Including a library’s predefined BOM in a project ensures that any library dependency imported into the project (direct or transitive) will be at the correct blessed version.

Now let’s see how the new Spring Framework’s BOM helps alleviate the above problem. We start by adding the following snippet to pom.xml file. Notice that we are using version 4.0.0.RC2.

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-framework-bom</artifactId>
            <version>4.0.0.RC2</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

The next step is to remove the version information for spring-context dependency:

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <exclusions>
      <!-- Use SLF4J. Not commons logging -->
      <exclusion>
         <groupId>commons-logging</groupId>
         <artifactId>commons-logging</artifactId>
      </exclusion>
   </exclusions>
</dependency>

This configuration will result in the right versions of all Spring dependencies (both direct and transitive) to be included in the project as shown below:
Blog 3

It is important to remember that adding a BOM simply doesn’t import all the declared artifacts. We still need to explicitly include the artifacts that we need except that we don’t have to declare their versions explicitly.

Categories: Maven Tags: , ,

Maven Multi Module Versioning

April 28th, 2010 6 comments

Recently I have been working on a Maven multi module project with ear, war and ejb artifacts. It has been a pleasant experience till I got to versioning my modules. Consider a multi module project with the following structure:

parent-project
|
|- child-moudle
| |
| |–pom.xml
|
|- pom.xml

The parent project pom.xml holds the version information of the parent project:

com.inflinx
project-parent
1.0.0-SNAPSHOT
pom

Now the child module pom contains a reference to the parent information:


	com.inflinx
	project-parent
	1.0.0-SNAPSHOT


4.0.0
com.inflinx
child-module
jar

Now this is where the problem starts. Since all the child modules need to have an explicit reference to the parent pom version, when it is time to do a release, we have to change the version in parent pom and all the child module poms. This can be a real pain and is very error prone. With a little help from Google, here is what I found:

  1. Ceki on his blog suggested using a property in the parent pom to control the version numbering.
  2. Several maven users would like “automatic parent versioning” according this improvement
  3. Use maven release plugin which would automate the process of changing version numbers across the project

Option three seems to be the correct approach to solve this problem here. But I have heard horrible things about the release plugin and how fragile it is. I will be giving it a try soon. I still think that Maven should support automatic parent versioning as an option for users who don’t (or cannot) get to use the release plugin.

Categories: Maven, Solutions Log Tags: ,

Creating Maven Archetypes – Spring MVC Example

April 16th, 2010 7 comments

Maven Archetypes are project templates that allow users easily create new projects. Maven Archetypes are great way to share best practices and enforce consistency beyond Maven’s standard directory structure. For example, an organization can provide its developers an archetype bundled with company’s approved CSS and JavaScript libraries.

Recently, I have been creating a lot of Spring MVC based projects and each time I do, I copy a lot of information (configuration files, css files, dependency information etc) from an existing project. Following the DRY principles, I decided to create several Spring MVC based archetypes that can help me bootstrap my projects quickly. In this post I will share my experiences creating and using a new Maven Archetype.

Maven provides several ways to create a new archetype as described here. Since I have an existing Spring MVC project, I will be using the archetype:create-from-project goal.

 

Creating Archetype

Step 1: Identify the Maven Project that would be used as prototype for the archetype. Make sure it has only the resources (configuration, properties and Java files) that you would like to be part of the archetype. It is recommended to remove IDE specific files (.project, .classpath etc) from the project directory. Here is the spring-mvc-prototype project that I will be using:

Prototype Project Layout

Prototype Project Layout

Step 2: Using command line, navigate to the project folder spring-mvc-prototype and run the following command:

	mvn archetype:create-from-project
	

Upon completion of the command, you should see the message “Archetype created in target/generated-sources/archetype”. The newly created archetype is now under spring-mvc-prototype/target/generated-sources/archetype

Step 3: The next step is to move the newly created archetype into a separate folder so that it can be tweaked and published. I have moved the content inside the spring-mvc-simple-archetype folder.

Archetype Directory Structure

Archetype Directory Structure

Step 4: Modify the artifactId in the archetype’s pom.xml located at the root of spring-mvc-simple-archetype folder.

Existing pom.xml:

  com.inflinx.blog
  spring-mvc-prototype-archetype
  1.0.0-SNAPSHOT
  maven-archetype
  spring-mvc-prototype-archetype

Modified pom.xml:

	com.inflinx.blog
	spring-mvc-simple-archetype
	1.0.0-SNAPSHOT
	maven-archetype
	spring-mvc-simple-archetype	

Step 5: Modify the finalName in the resource’s pom.xml file located at spring-mvc-simple-archetypesrcmainresourcesarchetype-resources.

		 
		spring-mvc-prototype

		
		${artifactId}
	

During project creation, maven will replace the ${artifactId} expression with the user supplied artifactId value.

Step 6: When creating a project from an archetype, Maven prompts the user for a package name. Maven will create the package in the source folder (srcmainjava) of the project being created and will move the contents under archetype-resourcessrcmainjava into the package.

Maven File Copy

Maven File Copy

While generating the “testproject” above, the user specified the package “com.inflinx.blog.testproject”. So the SomeJavaClass.java file got moved to the root of the package and the HomeController.java got moved under the web.controller subpackage.

Step 7: The next step is to verify that the generated archetype.xml (located under src/main/resources/META-INF/maven) has all the files listed and they are located in the right directories. For example, the HomeController is located under archetype-resources/src/main/java/web/controller/HomeController.java. So there should be an entry under sources in the archetype.xml that looks something like this:

	  
	    src/main/java/com/inflinx/blog/mvcprototype/web/controller/HomeController.java
	  

Step 8: Modify the configuration files to correctly use the ${package} variable. For example, the webContext.xml file is modified so that the controllers located under web.controller sub package are picked up:

		
	

Step 9: The final step in creating the archetype is to run the following on command line inside the folder spring-mvc-simple-archetype:

	mvn clean install
	

 

Using the archetype

Once the archetype is installed, there are several ways to create a project from it.

Generate goal: Create an empty folder and run the following command:

 		
 		mvn archetype:generate -DarchetypeCatalog=local
		

This goal would scan the local catalog for archetypes and prompts the user to select an archetype to use.

Command Line Archetype Usage

Command Line Archetype Usage

Once the user enters 1, Maven selects the spring-mvc-simple-archteype for project creation.

m2Eclipse Plugin: If you are an Eclipse user, use the New Project Wizard and search and select the spring-mvc-simple-archetype.

m2Eclipse Archetype Usage

m2Eclipse Archetype Usage

Using m2Eclipse plugin is a real time saver since it creates the associated IDE specific configuration files.

 

Adding Custom Properties

On some projects, additional information such as user name or web application context might be needed to generate the project. Here are the steps to prompt the user for information and use it:

Step 1: Add to the archetype-metadata.xml file located under spring-mvc-simple-archetypesrcmainresourcesMETA-INFmaven a required properties entry:

	
    	
  	

Step 2: Modify the file where you would like to use the information. Below, I have modified weblogic.xml to have the context root value the user has provided:

 
	
		
	        true
	    
		${contextRoot}	
	

When the user uses the archetype with the above modifications, he will be prompted for the contextRoot.

Custom Attribute Usage In Action

Custom Attribute Usage In Action