Lives in the UK. Likes blogging, cycling and eating lemon drizzle cake. Roger is a DZone MVB and is not an employee of DZone and has posted 143 posts at DZone. You can read more from them at their website. View Full User Profile

Dissecting Spring's MVC Project POM

09.26.2011
| 5996 views |
  • submit to reddit

One of the good things about Spring’s STS is that is provides a whole bunch of useful Spring project templates that you can use to generate empty or stub projects from which to start writing some code. The list of projects includes a ‘Simple Spring Utility Project’ and a ‘Spring Batch Admin WebApp’.



I’ve not had need to generate all these types of project, but I know that when you create a ‘Spring MVC Project’, you get a complete Maven webapp with a very complete POM file.

Opening up the WebApp’s pom.xml the first thing that strikes you is what a lot stuff you get - value for money or what? The file contains loads of dependencies and plugins and all kinds of stuff and it's all just to build a simple webapp. It does make you wonder whether it’s all needed, especially when you’re sitting in a cafe’ waiting whilst the empty application shell is downloading an endless string of JARs via a 3G connection.

This blog takes a look at the webapp’s POM file and tries to shed a little more light on what’s in there and why, and I’ve done that by commenting the original POM, which is below.

<?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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.captaindebug</groupId>
    <artifactId>test-and-delete</artifactId>
    <name>My Temp Web-App Project Name</name>
    <packaging>war</packaging>
    <version>1.0.0-BUILD-SNAPSHOT</version>
    <!-- 
    This is one of my favourite Maven tricks - specify the various dependency version
    out-right at the top of the file - making updating version very easy
     -->
    <properties>
        <java-version>1.6</java-version>
        <org.springframework-version>3.0.5.RELEASE</org.springframework-version>
        <org.springframework.roo-version>1.0.2.RELEASE</org.springframework.roo-version>
        <org.aspectj-version>1.6.9</org.aspectj-version>
        <org.slf4j-version>1.5.10</org.slf4j-version>
    </properties>
    <dependencies>
        <!-- These are the Spring dependencies, you need two 'context' and 'mvc' -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${org.springframework-version}</version>
            <!-- 
            It seems that the Guys at Spring have forsaken Common logging in 
            favour of SLF4J - not surprising as Commons Logging is notorious
            for having Class Loader problems (although I've never had any)
             -->
            <exclusions>
                <!-- Exclude Commons Logging in favor of SLF4j -->
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                 </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        
        <!--
        Okay, this is optional for a Java app and you can delete it. 
         -->
        <!-- Roo dependencies -->
        <dependency>
            <groupId>org.springframework.roo</groupId>
            <artifactId>org.springframework.roo.annotations</artifactId>
            <version>${org.springframework.roo-version}</version>
            <scope>provided</scope>
        </dependency>
                
        <!-- AspectJ optional if you're not into AOP -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${org.aspectj-version}</version>
        </dependency>    
        
        <!-- 
        Logging - this is the SLF4J configuration linking into Log4J 
        -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${org.slf4j-version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.15</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.mail</groupId>
                    <artifactId>mail</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>javax.jms</groupId>
                    <artifactId>jms</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jdmk</groupId>
                    <artifactId>jmxtools</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jmx</groupId>
                    <artifactId>jmxri</artifactId>
                </exclusion>
            </exclusions>
            <scope>runtime</scope>
        </dependency>

        <!-- 
        @Inject 
        This is JSR-330: Dependency Injection for Java - 
        the basic webapp will work without it
        -->
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>
                
        <!-- 
        These are straight forward Servlet/Web App/JSP dependencies
        nothing to see here
        -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    
        <!-- 
        Test dependencies - add in other libs like EasyMock here 
        -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.7</version>
            <scope>test</scope>
        </dependency>
        
    </dependencies>
    <!-- 
    If you're building a straight forward web-app with released versions 
    available at Maven Central then you don't really need this bit. 
    If you work for Spring and you're developing/testing then this 
    could be important
    -->
    <repositories>
        <!-- For testing against latest Spring snapshots -->
        <repository>
            <id>org.springframework.maven.snapshot</id>
            <name>Spring Maven Snapshot Repository</name>
            <url>http://maven.springframework.org/snapshot</url>
            <releases><enabled>false</enabled></releases>
            <snapshots><enabled>true</enabled></snapshots>
        </repository>
        <!-- For developing against latest Spring milestones -->
        <repository>
            <id>org.springframework.maven.milestone</id>
            <name>Spring Maven Milestone Repository</name>
            <url>http://maven.springframework.org/milestone</url>
            <snapshots><enabled>false</enabled></snapshots>
        </repository>
    </repositories>
    <build>
        <plugins>
            <!-- Okay, so you do need a compiler -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java-version}</source>
                    <target>${java-version}</target>
                </configuration>
            </plugin>
            <!-- 
            The WAR plugin is optional - it's used here to name the WAR output
            file - in this case abc.war
            -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <configuration>
                    <warName>abc</warName>
                </configuration>
            </plugin>
            <!-- 
            Resolves all the project's sources from the repositories 
            Optional - if you don't want to get hold of sources.
            -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>install</id>
                        <phase>install</phase>
                        <goals>
                            <goal>sources</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <!-- 
            This is required for AspectJ - allows you to weave in aspectJ stuff
            It's optional - if you're not using aspectj then you can 
            remove this plugin 
            -->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <!-- Have to use version 1.2 since version 1.3 does not appear to work with ITDs -->
                <version>1.2</version>
                <dependencies>
                    <!-- You must use Maven 2.0.9 or above or these are ignored (see MNG-2972) -->
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjrt</artifactId>
                        <version>${org.aspectj-version}</version>
                    </dependency>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjtools</artifactId>
                        <version>${org.aspectj-version}</version>
                    </dependency>
                </dependencies>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <outxml>true</outxml>
                    <source>${java-version}</source>
                    <target>${java-version}</target>
                </configuration>
            </plugin>
            <!-- 
            Surefire plugin - do some tests and generate some reports - 
            in this case exclude all Roo files
            -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <junitArtifactName>junit:junit</junitArtifactName>
                    <excludes>
                        <exclude>**/*_Roo_*</exclude>
                    </excludes>
                </configuration>
            </plugin>
            <!-- 
            Tomcat deployment plugin
            -->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>tomcat-maven-plugin</artifactId>
                <version>1.0-beta-1</version>
            </plugin>                        
        </plugins>
    </build>
</project>

I guess that the pom.xml should really be taken for what it is: a working sample. Most organisations I’ve come across generally organise their POM files in to some kind of hierarchy with a super-pom at the top containing the most general dependencies such as compiler plugin and version, or JUnit version etc, down to individual project POMs with the idea being that, to sprinkle in a few cliche's, you can line all your ducks up in a row, without duplicating effort and repeating yourself

 

From http://www.captaindebug.com/2011/09/dissecting-springs-mvc-project-pom.html

Published at DZone with permission of Roger Hughes, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Mladen Girazovski replied on Tue, 2011/09/27 - 8:58am

IMHO this example is not a working example of a real project.

Every project i've come accross using maven (most of the time i was responsible for the build) is composed of more than one single module, structured in a hierarchy as you say.

If a project consist of multiple modules (all real world projects are IME), it's time to apply some of the Maven best practices, namely using the dependencyManagement and pluginManagement sections, failing to apply the first one will result in redundancy, failing to apply the last one can result in a build that eventually fail, without you having changed anything. The problem of failing builds is reduced since some time (maven 2.0.9 introduced default plugin versions), but only for default plugins. Before that, without a pluginManagement section, maven would simply use the latest available plugin version, even it it broke your build...

There is more best practices for maven, google will help you find them.

Roger Hughes replied on Tue, 2011/09/27 - 10:34am in response to: Mladen Girazovski

I quite agree this isn't a working example of a real project. As I say in my last paragraph, the Guys at Spring (who wrote this) are only providing us with a sample, which I wouldn't use in a real world project. Like you, every real project I've come across is composed of multiple modules, for which the dependencyManagement tag was designed.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.