Archive

Archive for the ‘Maven’ Category

Maven – Bill Of Materials

December 29th, 2013 No comments

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: , ,

Spring Environment Profiles

August 26th, 2012 1 comment

Often time our web applications depend on properties that can change depending upon the environment (DEV/Stage/Production) the application is running. Examples of these include admin email addresses or URLs to communicate with web services. I am a big advocate of promoting the same war file across all the environments. In order to achieve that, I create separate property files and bundle them in the war file. Couple years ago, I wrote a custom Properties Holder implementation that would look at a JNDI key “Environment” and load the appropriate property file. Spring 3.1 introduces Environment Profiles that simplifies this entire process.

In this blog, I will create a web application and three property files each holding an email address that is specific to an environment. Then I will create bean profile definitions in Spring context file and activate them external to the web application.

We start by creating a Maven based web application using my Spring archetype. Here is the generated web application:
Spring MVC Maven Project

The next step is to create the following three property files in the src->main->resources folder:
Project_Dev.Properties

Project_Test.Properties

Project_Prod.Properties

Now, let’s modify the applicationContext.xml file to include the bean profiles each loading their respective property files. Here is the modified application-Context.xml file:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd">
	
	<!-- Load the dev property files by default -->
    <util:properties id="projectProperties" location="classpath:project_dev.properties"/>
 
 	<beans profile="Test">
 		<util:properties id="projectProperties" location="classpath:project_test.properties"/>
 	</beans>
 	
 	<beans profile="Prod">
 		<util:properties id="projectProperties" location="classpath:project_prod.properties"/>
 	</beans>
       
</beans>       		

	

Notice that we are using Spring’s new 3.1 schema definitions in the context file. The context file has two profiles one for test and one for production. By default, Spring would load all the properties from the project_dev.properties file. Also observe that we have used the same id for all the util:properties beans.

We then modify the HomeController class and home.jsp file to read and display the “admin.email” property. We do that using the @Value annotation in the HomeController and add it to Model as shown below:


package com.inflinx.blog.springprofiles.web.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/home.html")
public class HomeController 
{
	@Value("#{projectProperties.adminEmail}") 
	private String adminEmail;
	
	@RequestMapping(method = RequestMethod.GET)
	public String showHome(Model model) 
	{
		model.addAttribute("adminEmail", adminEmail);
		return "home";
	}
	
}

Finally, we modify the home.jsp page to show the email property:

<%@ taglib uri=”http://java.sun.com/jsp/jstl/core” prefix=”c” %>
<%@ page session=”false” %>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>
Admin Email: ${adminEmail}
</h1>

</body>
</html>

Deploy the application and you should see the default dev admin email in the browser:
Browser Dev Email

To activate the Test profile, add the Environment Variable spring.profiles.active with value Test. In Windows, you can do that by going to Advanced Settings -> Environment Variable -> New
Environment Variables

If you are running your Application Server from Eclipse, restart Eclipse and redeploy the app. In the logs you should be able to see that Spring has activated Test profile:
Spring Active Profiles

Upon refreshing the browser, you should see the new admin email:
Test Admin Email

Categories: Maven, Spring Tags:

Spring MVC 3.1.1 Archetype

May 18th, 2012 No comments

I have created a new Maven archetype for creating Spring MVC 3.1.1 based web applications.

To install the archetype, download the file and simply run the following command:

mvn install:install-file -DgroupId=com.inflinx.blog -DartifactId=spring-mvc-web-archetype -Dversion=1.0.0 -Dpackaging=jar -Dfile=spring-mvc-web-archetype-1.0.0.jar

The above command needs to be run from the directory where you have placed the downloaded file.


To use the installed archetype run the following command from your project folder:

mvn archetype:generate -DarchetypeGroupId=com.inflinx.blog -DarchetypeArtifactId=spring-mvc-web-archetype -DarchetypeVersion=1.0.0 -DgroupId=com.inflinx.blog -DartifactId=YOUR_PROJECT_NAME -DartifactVersion=1.0.0 -DinteractiveMode=false

If you are interested in creating your own archetypes refer to my Creating Maven Archetypes – Spring MVC Example blog post.

Categories: Maven, Spring 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

Changing Maven4MyEclipse Web Project Directory Structure

September 11th, 2008 No comments

When you create a MyEclipse Web Project with Maven capabilities, the generated directory structure does not match the “standard” Maven Web Project structure. I find this little annoying and here is what I did to change the directory structure:

  • Under “src” folder, create two folders main and test. Underneath each folder create two folders java and resources
  • Go to project properties and under Java Build Path, first remove “src” folder from being a source folder. Make java and resources folders source folders
  • Create webapp folder underneath src/main. Create WEB-INF and classes folders under webapp. Move the web.xml under WebRoot/WEB-INF to webapp/WEB-INF folder
  • In the .mymetadata file located in the project root folder (use Navigator view to get to the file in MyEclipse), change the attribute webrootdir’s value to /src/main/webapp
  • In the .classpath file, change the classpathentry of kind “output” from “WebRoot/WEB-INF/classes” to “src/main/webapp/WEB-INF/classes”
  • Delete the WebRoot directory and restart MyEclipse

The original pom.xml generated as part of the Maven4MyEclipse Web Project has several entries (sourcedirectory, resource directory e.t.c.) to reflect MyEclipse Web project directory structure. These entries can be safely deleted. Once this is done, the new project can be used to hot-deploy the war file. And yes, dependencies declared as “test” will not end up in the lib directory of the hot-deployed war file.

Maven4MyEclipse Bug

August 27th, 2008 No comments

I have not been quite impressed with MyEclipse’s Maven4MyEclipse plugin. The most disappointing thing about this is that after checking out an existing project from source control, I cannot add Maven “capabilities” using the context menu (which could be easily done with m2eclipse).

For the last couple days, I am running into this wierd bug with the “Java Maven Wizard”: When I try to check out an existing project from SVN using: “Find/Check Out As” -> “Check Out as a project configured using the New Project Wizard” -> “Java Maven Project” into a location other than the default location provided by the wizard, the wizard still checks out the project into the default location.

Hopefully I will have some solution in the Maven4MyEclipse forum.

Update: Looks like the same issue surfaces for newly created Java Maven projects also.

Categories: Maven, MyEclipse Tags: