Tag Archives: static analysis

Using the right tool the right way: Maven 2 (or 3)

Maven is sometimes referred to as a Rube Goldberg machine and is probably one of the most controversial tool used in the java community. Many people just hate it, I can’t help thinking it’s only because they don’t use it the right way. In the reality I experienced , Maven 2 is really good at making project management very simple. You just have to follow a few rules to avoid getting into a mess.

1. Maven is not a replacement for Ant

If you have a complex project built with Ant, just don’t migrate it to Maven. It’s not worth the pain. Maven works fine only if you follow its conventions, especially the directory structure.

Yes, there is Maven Antrun Plugin allowing to run ant tasks from Maven. That could be useful to integrate a legacy component into a new project without changing the way this component is built. Apart from that, it shouldn’t be used. The worst usage of this plugin is to do something with Ant that you’re not able to figure out with Maven. If it’s really not possible with Maven, it probably reveals a bigger problem in the way your project is set-up.

2. Don’t let your dependencies grow out-of-control

Here are a few things to pay attention to:

  • Keep your dependencies to the minimum in each pom file. A common mistake is to start a new module by copy-pasting an existing pom.xml, that’s a bad idea if you reuse few of its dependencies.
  • Try as mush as possible to avoid the use of <exclusions> or <optional> elements.  As recommended by the Maven team, they’re a last resort solution and shouldn’t be used for any quick-fix.
  • Don’t use system scope dependencies to deal with proprietary jar files. Instead create a corporate repository or, if you can’t, use a file repository using the technique described here.
  • For any big application, use a parent POM with a <dependencyManagement> element to control all the dependencies used accross multiple modules and keep your children POM to the minimum, as follow:

Parent POM

<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.domain.group</groupId>
    <artifactId>parent</artifactId>
    <packaging>pom</packaging>
    <version>1.0</version>
    <modules>
        <module>../child1</module>
        <module>../child2</module>
        <module>../child3</module>
        <module>../child4</module>
    </modules>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz</artifactId>
                <version>1.8.3</version>
            </dependency>
            <dependency>
                <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz-oracle</artifactId>
                <version>1.8.3</version>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.16</version>
            </dependency>
    </dependencyManagement>
</project>

Child POM

<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.domain.group</groupId>
    <artifactId>child1</artifactId>
    <parent>
        <artifactId>parent</artifactId>
        <groupId>com.domain.group</groupId>
        <version>1.0</version>
        <relativePath>../parent</relativePath>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-oracle</artifactId>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </dependency>
    </dependencies>
</project>

3. Rely on plugins

What is so great with Maven and that you’ll find nowhere else is that there is a plugin for pretty much everything, which is normal because Maven has been thought as a plugin framework, all the work is done by plugin. Some plugins come obviously out-of-the-box to allow for the most common tasks. Many others are available in various repositories. And finally, if you don’t find any to do your very specific task, just write your own, it will integrate smoothly in your build.

Here are a few examples of real life problems and how to solve them with maven:

  • You want to run automated unit tests (if not, you should), just put them in the test directory and the surefire plugin will run them for you.
  • You want to create an archive containing scripts, configuration files and jar files, check the assembly plugin.
  • You have an XML interface? Just put your XSD file with your sources and use jaxb2 or xmlbeans plugin to generate classes on the fly.
  • Working with hibernate 3? hibernate 3 plugin will ease your life.
  • Want to run SQL script? … well you get it, use sql plugin.

All those plugins along with the way Maven is designed, allow to integrate your project with many other useful tools: IDE such as Eclipse (of course), continuous integration such as Hudson, or quality management like Sonar.

Maven rocks!

<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.cgi.sipcip</groupId>
<artifactId>SipCipPackageBuilder</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<name>SipCipPackageBuilder</name>
<description>Project which unique goal is to build and package the jars/wars of its modules(other eclipse projects), depending on their pom.xml</description>

<modules>
<module>../SipCipCommons</module>
<module>../CommonJobsScheduler</module>
<module>../SipCipWeb</module>
<module>../BroadsoftClient</module>
<module>../RestletClient</module>
<module>../BroadsoftNsClient</module>
<module>../CIPConfigurationClient</module>
<module>../SipCipOrchestrator</module>
<module>../SipCipActivator</module>
<module>../SipCipJobsScheduler</module>
<module>../DbEntitiesToXmlConverter</module>
<module>../VmCipJobsScheduler</module>
</modules>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>com.cgi.sipcip</groupId>
<artifactId>sipCipCommons</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.cgi.sipcip</groupId>
<artifactId>SipCipOrchestrator</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.cgi.sipcip</groupId>
<artifactId>commonJobsScheduler</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.cgi.sipcip</groupId>
<artifactId>CIPConfigurationClient</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.cgi.sipcip</groupId>
<artifactId>RestletClient</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.cgi.sipcip</groupId>
<artifactId>BroadsoftNsClient</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.cgi.sipcip</groupId>
<artifactId>BroadSoftClient</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.cgi.sipcip</groupId>
<artifactId>DbEntitiesToXmlConverter</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>1.8.3</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-oracle</artifactId>
<version>1.8.3</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.1.0.Final</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.restlet.jse</groupId>
<artifactId>org.restlet</artifactId>
<version>2.0-M5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-scm-plugin</artifactId>
<version>1.3</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>

<properties>
<spring.version>2.5.6.SEC01</spring.version>
</properties>

<repositories>
<repository>
<id>Maven2</id>
<name>Maven2 Repository</name>
<url>http://repo2.maven.org/maven2</url>
</repository>
<repository>
<id>JBOSS</id>
<name>JBoss Repository</name>
<url>http://repository.jboss.com/maven2</url>
</repository>
<repository>
<id>JBOSS.org</id>
<name>JBoss.org Repository</name>
<url>http://repository.jboss.org</url>
</repository>
<repository>
<id>JBOSS Nexus</id>
<name>JBoss Nexus Repository</name>
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
</repository>
<repository>
<id>maven2-repository.dev.java.net</id>
<name>Java.net Maven 2 Repository</name>
<url>http://download.java.net/maven/2</url>
</repository>
<repository>
<id>maven-repository.dev.java.net</id>
<name>Java.net Maven 1 Repository (legacy)</name>
<url>http://download.java.net/maven/1</url>
<layout>legacy</layout>
</repository>
<repository>
<id>Itextpdf.org</id>
<name>Itextpdf.org Repository</name>
<url>http://maven.itextpdf.com</url>
</repository>
<repository>
<id>maven-restlet</id>
<name>Public online Restlet repository</name>
<url>http://maven.restlet.org</url>
</repository>
<repository>
<id>sipcip-local-repo</id>
<url>file://${basedir}/../SipCipPackageBuilder/sipcip-repo</url>
</repository>
</repositories>

<pluginRepositories>
<pluginRepository>
<id>maven2-repository.dev.java.net</id>
<name>Java.net Maven 2 Repository</name>
<url>http://download.java.net/maven/2</url>
</pluginRepository>
<pluginRepository>
<id>maven-repository.dev.java.net</id>
<name>Java.net Maven 1 Repository (legacy)</name>
<url>http://download.java.net/maven/1</url>
<layout>legacy</layout>
</pluginRepository>
</pluginRepositories>

</project>