Anteo Java News: Summer 2006
We appreciate and welcome all of your comments and submissions as we are tailoring the newsletter for you. Please send any comments and/or submissions for future articles to Anteo Group Marketing. To receive Anteo Java News by email, contact us.
Thanks and enjoy!
Getting started with Maven 2.0
By: James Mitchell
This article is based on my personal experience as well as the many great resources currently available on this subject. For the most current and complete guide to using Maven 2, check out the free PDF titled "Better builds with Maven" found here: http://www.mergere.com/m2book_download.jsp
What is Maven?
It would be nice to say that Maven is like "this tool" or like "that framework", but there is no other framework that does what the Apache Maven framework does.
Maven's documentation will tell you that it is a "software project management and comprehension tool." Though this description does little to satisfy the curiosity of the passer-by, someone who comes across the link to Maven's home page while reading news feeds or a blog is about as close as you can get to describe what Maven offers its users. You'll see what I mean after you try the sample below.
How Does Maven Work?
Maven offers a standard approach to building and deploying your software projects-and much more. At its core, Maven's architecture is simple and elegant. Maven provides a pluggable and extendable library that implements a well-defined lifecycle given the type of project that you've defined. Maven Plugins are created to hook into, extend, and even short-circuit this lifecycle.
For the example below, we'll be primarily focused on creating and building a Java Archive (Maven project of type "jar.")
For more details on Maven's lifecycle, see
this page.
A typical Maven project has a single artifact as its output. This artifact can be a JAR, WAR or EAR. When multiple artifacts are needed, they become modules of a parent project. In this case, the parent project type would be of type "pom" and would declare its children as <modules> within its pom.xml. More information about multi-project builds can be found online and in the referenced PDF at the start of this article.
The example below will compile the source code and run the unit tests as well as package it into a JAR. Sound simple enough?
ANT vs. Maven
At this point, you might be thinking, "Why not just use Ant?" Ant works well for what it does, there's no need to argue that point. If you have a simple project, Ant is really all you need. It's when your project grows in size and complexity where Maven really shines.
Maven helps you deal with project versioning, dependency management, deployment, and many other advanced build management tasks. Maven's support for transitive dependency management alone is enough for some to run with Maven and never look back.
Have Some Patience
When first introduced to Maven, some people get frustrated quickly and give up, never giving Maven a chance to prove itself. Long time Ant users are the worst. I think part of the problem is due to our indoctrination with building Ant scripts. With Ant, we "tell" it what to do, when to do it, and we manually setup the environment for which it is to do it. Take this in contrast to Maven, where we just tell it what our project looks like, and Maven does everything else. It's quite a different paradigm.
For years we have been writing and maintaining Ant build.xml files for every project we work on, project to project, job to job. As we move onward and upward, we take along our toolsets, including our build tools and habits, both good and bad.
Just as you have a favorite style of writing code, you will also have a favorite way of scripting an Ant build. There are definitely right and wrong ways to use Ant, but my "right" can vary greatly from your "right". The more time we spend on a given project, the more ingrained we become to building a certain way. If you start on a new project and it is similar to a former one, you would be lucky if you could simply copy/paste and replace a few things here and there. However, most of us are not that fortunate.
And as a project grows, it must adapt and handle new tasks. An elegant build can handle this easily, but what if you inherited some atrocious hack that you spend more time fixing than you do writing code? What is there to do? Herein lays the beauty of Maven.
The Benefits of Familiarity
If you work on multiple projects/products or leave one project/job to work on another, and if they were both based on Maven, you already know 80% of how the build works. Combine that with a ten-minute perusal through the file system and you're at about 90%. You'll know where to look for java sources, runtime as well as test-only resources, taglibs, and so forth. You can see right away how dependencies are used, rather than searching around looking for imported or delegated alternate build scripts and trying to figure out what the actual classpath is for this or that compile execution.
Ok, that's enough sales for now.
Let's Try It Out:
- Download Maven - http://maven.apache.org/download.html
- Add the Maven executable (e.g. maven-bin-2.0.4/bin/mvn) to your PATH (similar to how you would manually add any executable to your system PATH -- Ant, the Java JDK and/or JRE, etc. See the bottom of the download page for more details.)
Next, we will directly execute a Maven plugin (Maven Archetype Plugin) that is used to create a small project based on some provided information. Think of an archetype as something like a template or cookie cutter to jump-start your project.
Open a command shell and execute the following command in the directory of your choosing (all on one line):
> mvn archetype:create
-DgroupId=com.mycompany.quickstart
-DartifactId=my-maven-archetype-quickstart
-DarchetypeArtifactId=maven-archetype-quickstart
> cd my-maven-archetype-quickstart
Note - If you are behind a proxy, you'll need to configure Maven to use your proxy settings: http://maven.apache.org/guides/mini/guide-proxies.html.
So, what did you just do?
You just created a sample shell of a project that you can use as the basis for a new Maven project. You may have noticed that 3 files were created for you.
- A Project Object Model (pom.xml)
- A Java source file (App.java)
- A JUnit test (AppTest.java)
Now try this:
> mvn install
You just built and deployed the new library into your local repository. If you needed this new library in a different project, you could add the dependency, and Maven would use it without knowing that this was also a local project.
The "local repository" that was just mentioned is the location on your hard drive that holds local copies of Maven resources. These resources are typically JARs and Maven meta data about the stored versions of JARs. This location will be the following directory: {user.home}/.m2/repository/
The "user.home" directory is your home directory. I'll be referring back to this later in the article.
If you are on Microsoft Windows, your {user.home} is usually a directory under C:\Documents and Settings\ with your login name.
Look under {user.home}
/.m2/repository/com/mycompany/quickstart/
my-maven-archetype-quickstart/
You'll see a directory structure with something like this:
1.0-SNAPSHOT/
maven-metadata-local.xml
my-maven-archetype-quickstart-1.0-SNAPSHOT.jar
my-maven-archetype-quickstart-1.0-SNAPSHOT.pom
maven-metadata-local.xml
Specific details about what each file means is beyond the scope of this article. However, for now, just know that when you execute "install," Maven will (unless the build fails) add the artifact (a jar in our case) to the local repository so that any other projects that you build can use that new JAR.
Now try this:
> mvn site
At this point, all we've done is execute a few commands, and without adding a single line of code or xml, Maven will generate a basic web site for you (look in the target/site/ directory.) Open index.html and take a look at what was generated.
You'll see basic information about your new project including a report about your project's dependencies, any mailing lists or licensing. As wonderful as this is, out of the box, the default set of pages give little more than window dressing read from the project meta descriptions in the pom.xml file. Maven also allows you to generate any number of extra site documents by adding a few xml files under a folder called, intuitively, "site." This brief description of Maven's site generation is merely the tip of the iceberg for what can be done with site documentation.
My IDE of choice is Eclipse. So, now I want to create a new Eclipse project from my newly generated maven project.
> mvn eclipse:eclipse
If you are using Eclipse, you'll see that the above command generates the .project and .classpath files for you. Create a new project in Eclipse, pointing the base directory for the project at the generated project's directory, and you'll see that the source files, test files, dependencies, and output paths are all setup correctly.
There are plugins for many of the popular IDEs, for example, here is the URL for the Maven IDEA Plugin:
http://maven.apache.org/plugins/maven-idea-plugin/idea-mojo.html
Note -- The Eclipse plugin uses a workspace variable called "M2_REPO" that should point to your local Maven repository. As mentioned above, this will be your {user.home}/.m2/repository directory. You will only have to do this once per workspace, the variable is global to other Eclipse projects within the workspace. This really helps out if you must share the configuration between developers, since each can have their own definition of what M2_REPO means on their machine.
Now that we have the project in our IDE, let's add a report. Cobertura is an open source Java tool that measures and reports on test coverage. The friendly folks at Codehaus make a Maven plugin that minimizes the work required to use Cobertura.
Open the pom.xml and add the following:
<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.mycompany.quickstart</groupId>
<artifactId>my-maven-archetype-quickstart</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<reporting>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
</plugin>
</plugins>
</reporting>
</project>
Now run the site goal again. This time we will precede it with the "clean" goal, which will remove the output directory.
> mvn clean site
You'll see Maven downloading the necessary plugin and dependencies, then Maven will rerun the site plugin, but this time Cobertura will instrument the code and rerun the test. The output results will be collected and used to generate a new report that gets neatly placed into your new site. Refresh the site in your browser that you opened earlier (target/site/index.html.)

Click on the image for a larger view.
If, by chance, Maven fails to run the site goal successfully, chances are pretty good that there were problems downloading the plugin or some of its dependencies. If so, just rerun it. Sometimes the default repositories are overloaded and a download will fail. If the problem continues, make sure it's not due to a proxy misconfiguration or something as simple as an unplugged network cable.
So let's add a real test and bring up out test coverage percent. Open App.java and add a demo() method. Feel free to remove the main method.
App.java
package com.mycompany.quickstart;
/**
* Hello world!
*
*/
public class App
{
public String demo()
{
return "Hello World!";
}
}
AppTest.java
package com.mycompany.quickstart;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase
{
// some code removed for brevity
/**
* Rigourous Test :-)
*/
public void testApp()
{
App app = new App();
assertEquals("Testing demo method", app.demo(), "Hello World!");
}
}
Run the site goal again.
> mvn clean site

Click on the image for a larger view.
Ok, much better. We now have a brand new, Maven-ized java project at 100% test coverage.
There is much more to Maven than what I've covered in this article. There are so many plugins, such that if you can imagine it, there's probably a plugin for it. As you use Maven in your own projects, like any new tool, there will be times where you get frustrated about one thing or another, whether it's a build failure that eludes a resolution or the discovery of a few "undocumented features" of some version of a plugin that you depend on. I would encourage you to hang in there; it gets better as you become more familiar and thus comfortable with Maven.
Additional resources:
The Apache Maven project:
http://maven.apache.org/
The Maven Plugin Matrix - This site is not being updated, but it does provide good information on where a certain plugin may live:
http://docs.codehaus.org/display/MAVEN/Maven+Plugin+Matrix
More Maven plugins:
http://maven.apache.org/plugins/index.html
http://svn.mojo.codehaus.org/trunk/mojo/
http://xdoclet.sourceforge.net/xdoclet/maven-plugin.html
http://maven-plugins.sourceforge.net/projects-overview.html
About the Author:
James Mitchell is a freelance Java consultant based out of Atlanta, GA. In addition to consulting, James serves as a committer and Project Management Committee member for the Apache MyFaces, Apache Shale, and Apache Struts projects. Outside of Java, James enjoys spending time with his wife and three children. It is still a mystery as to how he finds time to do all he does and still coach all three of their soccer teams.
To contact James Mitchell, send an email to jmitchell@apache.org or
call 678.910.8017.
Setting Up a Continuous Integration Environment
- Small Investment, Big Return
By: Mike Dunbar
Software gurus have been preaching the benefits of 'Continuous Integration' for years. Though widely considered a best practice, it is surprisingly absent from many projects. In this article, we'll discuss the reasons to implement Continuous Integration, the value it brings to your project, free tools that can be used to accomplish it, and ways to overcome some of the concerns of teams adopting it for the first time.
Simply defined, Continuous Integration is integrating your code base every time a change is made. It's an on-going health check of the state of your code. It's all about feedback - feedback on whether or not your project is still "working." What exactly is meant by "working?" Whatever your team considers important and has incorporated into your integration scripts. This typically includes things like compilation/packaging, deployment, and some measure of testing. It may even include checks for code coverage, or for adherence to coding and architectural guidelines. The point is, every time the project is updated (at least, at scheduled intervals) the Continuous Integration system ensures it still works. If it doesn't, the team is alerted (e.g., by email,) and it becomes their top priority to get it working again. That's the primary benefit of Continuous Integration - timely feedback to keep your project in a working state. After all, why add new features when existing ones don't work?
There are other significant benefits to Continuous Integration as well. For instance, automated tests are naturally more likely to stay up-to-date because you are regularly running them. When tests are not regularly run, they're too easily abandoned as the project deadline approaches. Another important benefit is that developer productivity isn't hampered by broken code getting into the project base. That can happen, for example, when a team member forgets to check in a new 3rd party library required by the feature they just added. With Continuous Integration, such oversights are found and corrected immediately.
Even if this all sounds great, you may be thinking that there's too much effort required to set up a Continuous Integration environment. There is the cost of initial setup and maintenance time. Otherwise, it's remarkably simple, and there's plenty of good free tool support available. The components of a Continuous Integration environment, along with some free tool options, are list below.
| Component |
Free Options |
| * Dedicated build machine |
Old/unused office PC |
* Build Scheduling System |
Anthill, CruiseControl |
| * Build Script(s) |
Ant, Maven |
| * Version Control System |
CVS, Subversion |
| Automated Unit Tests |
JUnit, TestNG |
| Automated System Tests |
TestMaker , Fit |
| * = mandatory |
A dedicated build machine provides the important function of a standard environment, avoiding the all too common scenario where the build works on one person's machine but not on another. Build scripts, of course, define and orchestrate various tasks like packaging, deployment, and testing. The scheduling system retrieves the project from the version control system and executes the build scripts at defined intervals. Unit and system tests give greater confidence that the system is working - the better the test coverage, the higher the confidence. We're all using at least half of these components on our projects already. Adding the others and tying it all together doesn't take more than a day, so what's stopping everyone?
Development teams can quote a host of reasons to resist implementing Continuous Integration. I'll discuss some of the more common excuses and why I believe this resistance should be overcome:
1. "Daily builds sound excessive, let alone building every hour."
Frequent builds do represent a change, but the longer you wait to integrate, the bigger the issues can become. Without a health check, developers simply have that much longer to continue in the wrong direction. Better to uncover and rectify misconceptions hours, rather than days or weeks later.
2. "Schedule builds will kick off while developers are in the middle of committing project changes, generating false alarms."
This does happen (though rarely in my experience) but is easily rectified. The report from any decent build scheduling system details both the error and the set of updated files. It's immediately obvious what happened, and the build succeeds on retry.
3. "Fear of breaking Continuous Integration builds will prevent people from checking in changes for long periods."
There are situations where we need to make sweeping changes and just won't be able to get the build working for a while. This concern is completely unwarranted because no one should commit unstable code that can disrupt team members, nor go long periods without committing changes whether the team is practicing Continuous Integration or not. In either case, the solution is rather simple. Create a separate code branch for the work and merge it back to the main project (where Continuous Integration would be running,) only when it's finally working.
Continuous Integration maintains the health of your project. Issues are identified and corrected while they're still easily managed, rather than days or weeks later. Continuous Integration forces adherence to best practices which might otherwise be missed in the chaos inherent to modern software projects. The time investment is minimal and more than pays for itself throughout the life of your project. Don't take my word for it though, go ahead and give it a try on your current project.
About the Author
Mike Dunbar works as a software engineer at InterCall, the largest
provider of conference communication services. His technical interests
included design/architecture, process (agile, in particular), and
automation. He can be reached at mdunbar@intercall.com.
Current Openings
For our most current openings, click here.
back to newsletters >
For more information about the Anteo Group, contact us.